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 2022/08/30 19:54:52 UTC

[plc4x] branch develop updated (24e8bf91e -> 6e6507ba5)

This is an automated email from the ASF dual-hosted git repository.

cdutz pushed a change to branch develop
in repository https://gitbox.apache.org/repos/asf/plc4x.git


    from 24e8bf91e refactor(plc4go/connection-cache): cleanup
     new 16c7d377a fix(protocols/bacnet): Updated the URL for fetching the vendor ids
     new 1045cf01a fix(plc4j): Changed the SPI to pass along PlcAuthentication information to the ProtocolLogic
     new 6e6507ba5 fix(plc4j/ads): Implemented the automatic adding of AMS routes in Beckhoff PLCs

The 3 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 plc4j/drivers/ads/pom.xml                          |  4 ++
 .../plc4x/java/ads/protocol/AdsProtocolLogic.java  | 75 ++++++++++++++++++++++
 .../plc4x/java/can/adapter/CANDriverAdapter.java   | 10 +--
 .../conversation/ConversationContextWrapper.java   | 11 +++-
 .../apache/plc4x/java/opcua/OpcuaPlcDriver.java    |  9 +--
 .../simulated/connection/SimulatedConnection.java  |  3 +-
 .../apache/plc4x/java/spi/ConversationContext.java |  3 +
 .../apache/plc4x/java/spi/Plc4xNettyWrapper.java   | 35 ++++++++--
 .../java/spi/connection/AbstractPlcConnection.java | 12 +++-
 .../connection/CustomProtocolStackConfigurer.java  | 12 ++--
 .../spi/connection/DefaultNettyPlcConnection.java  | 11 ++--
 .../java/spi/connection/GeneratedDriverBase.java   | 15 +++--
 .../java/spi/connection/NettyChannelFactory.java   |  9 ++-
 .../spi/connection/ProtocolStackConfigurer.java    |  8 +--
 .../connection/SingleProtocolStackConfigurer.java  | 13 ++--
 .../plc4x/java/spi/Plc4xNettyWrapperTest.java      |  2 +-
 .../bacnetip/src/main/script/getVendorIds.groovy   |  2 +-
 .../org/apache/plc4x/java/df1/DF1PlcDriver.java    |  1 -
 18 files changed, 181 insertions(+), 54 deletions(-)


[plc4x] 01/03: fix(protocols/bacnet): Updated the URL for fetching the vendor ids

Posted by cd...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

cdutz pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/plc4x.git

commit 16c7d377a59e45ea933a48cd09a148c237f2c4f7
Author: Christofer Dutz <ch...@c-ware.de>
AuthorDate: Tue Aug 30 21:51:07 2022 +0200

    fix(protocols/bacnet): Updated the URL for fetching the vendor ids
---
 protocols/bacnetip/src/main/script/getVendorIds.groovy | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/protocols/bacnetip/src/main/script/getVendorIds.groovy b/protocols/bacnetip/src/main/script/getVendorIds.groovy
index 0943ce1f1..0bf9e636b 100644
--- a/protocols/bacnetip/src/main/script/getVendorIds.groovy
+++ b/protocols/bacnetip/src/main/script/getVendorIds.groovy
@@ -45,7 +45,7 @@ if (bacnetVendorHtm.exists()) {
 // If we need to update the vendor ids
 if (update) {
     try {
-        InputStream inputStream = new URL("http://www.bacnet.org/VendorID/BACnet%20Vendor%20IDs.htm").openStream()
+        InputStream inputStream = new URL("https://bacnet.org/assigned-vendor-ids/").openStream()
         Files.copy(inputStream, bacnetVendorHtm.toPath(), StandardCopyOption.REPLACE_EXISTING)
         println "Successfully updated BACnet Vendor IDs.htm"
     } catch (Exception e) {


[plc4x] 02/03: fix(plc4j): Changed the SPI to pass along PlcAuthentication information to the ProtocolLogic

Posted by cd...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

cdutz pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/plc4x.git

commit 1045cf01a525acddf118ecfb1916df3f84921853
Author: Christofer Dutz <ch...@c-ware.de>
AuthorDate: Tue Aug 30 21:54:09 2022 +0200

    fix(plc4j): Changed the SPI to pass along PlcAuthentication information to the ProtocolLogic
---
 .../plc4x/java/can/adapter/CANDriverAdapter.java   | 10 +++----
 .../conversation/ConversationContextWrapper.java   | 11 ++++++-
 .../apache/plc4x/java/opcua/OpcuaPlcDriver.java    |  9 ++----
 .../simulated/connection/SimulatedConnection.java  |  3 +-
 .../apache/plc4x/java/spi/ConversationContext.java |  3 ++
 .../apache/plc4x/java/spi/Plc4xNettyWrapper.java   | 35 +++++++++++++++++-----
 .../java/spi/connection/AbstractPlcConnection.java | 12 ++++++--
 .../connection/CustomProtocolStackConfigurer.java  | 12 +++++---
 .../spi/connection/DefaultNettyPlcConnection.java  | 11 ++++---
 .../java/spi/connection/GeneratedDriverBase.java   | 15 +++++-----
 .../java/spi/connection/NettyChannelFactory.java   |  9 +++---
 .../spi/connection/ProtocolStackConfigurer.java    |  8 ++---
 .../connection/SingleProtocolStackConfigurer.java  | 13 +++++---
 .../plc4x/java/spi/Plc4xNettyWrapperTest.java      |  2 +-
 .../org/apache/plc4x/java/df1/DF1PlcDriver.java    |  1 -
 15 files changed, 101 insertions(+), 53 deletions(-)

diff --git a/plc4j/drivers/can/src/main/java/org/apache/plc4x/java/can/adapter/CANDriverAdapter.java b/plc4j/drivers/can/src/main/java/org/apache/plc4x/java/can/adapter/CANDriverAdapter.java
index aa48fb14c..13eecb845 100644
--- a/plc4j/drivers/can/src/main/java/org/apache/plc4x/java/can/adapter/CANDriverAdapter.java
+++ b/plc4j/drivers/can/src/main/java/org/apache/plc4x/java/can/adapter/CANDriverAdapter.java
@@ -62,22 +62,22 @@ public class CANDriverAdapter<C, T> extends Plc4xProtocolBase<C> {
 
     @Override
     public void setContext(ConversationContext<C> context) {
-        delegate.setContext(new ConversationContextWrapper<>(context, wireType, adapter, frameHandler));
+        delegate.setContext(new ConversationContextWrapper<>(context, wireType, adapter, frameHandler, context.getAuthentication()));
     }
 
     @Override
     public void onConnect(ConversationContext<C> context) {
-        delegate.onConnect(new ConversationContextWrapper<>(context, wireType, adapter, frameHandler));
+        delegate.onConnect(new ConversationContextWrapper<>(context, wireType, adapter, frameHandler, context.getAuthentication()));
     }
 
     @Override
     public void onDisconnect(ConversationContext<C> context) {
-        delegate.onDisconnect(new ConversationContextWrapper<>(context, wireType, adapter, frameHandler));
+        delegate.onDisconnect(new ConversationContextWrapper<>(context, wireType, adapter, frameHandler, context.getAuthentication()));
     }
 
     @Override
     protected void decode(ConversationContext<C> context, C msg) throws Exception {
-        delegate.decode(new ConversationContextWrapper<>(context, wireType, adapter, frameHandler), frameHandler.fromCAN(adapter.apply(msg)));
+        delegate.decode(new ConversationContextWrapper<>(context, wireType, adapter, frameHandler, context.getAuthentication()), frameHandler.fromCAN(adapter.apply(msg)));
     }
 
     @Override
@@ -102,7 +102,7 @@ public class CANDriverAdapter<C, T> extends Plc4xProtocolBase<C> {
 
     @Override
     public void close(ConversationContext<C> context) {
-        delegate.close(new ConversationContextWrapper<>(context, wireType, adapter, frameHandler));
+        delegate.close(new ConversationContextWrapper<>(context, wireType, adapter, frameHandler, context.getAuthentication()));
     }
 
 }
diff --git a/plc4j/drivers/can/src/main/java/org/apache/plc4x/java/can/adapter/conversation/ConversationContextWrapper.java b/plc4j/drivers/can/src/main/java/org/apache/plc4x/java/can/adapter/conversation/ConversationContextWrapper.java
index fb18127e2..930b0a15f 100644
--- a/plc4j/drivers/can/src/main/java/org/apache/plc4x/java/can/adapter/conversation/ConversationContextWrapper.java
+++ b/plc4j/drivers/can/src/main/java/org/apache/plc4x/java/can/adapter/conversation/ConversationContextWrapper.java
@@ -22,6 +22,7 @@ import io.netty.channel.Channel;
 import java.time.Duration;
 import java.util.function.Function;
 
+import org.apache.plc4x.java.api.authentication.PlcAuthentication;
 import org.apache.plc4x.java.spi.ConversationContext;
 import org.apache.plc4x.java.spi.configuration.Configuration;
 import org.apache.plc4x.java.transport.can.CANTransport.FrameHandler;
@@ -34,11 +35,19 @@ public class ConversationContextWrapper<C, T> implements ConversationContext<T>
     private final Function<C, FrameData> adapter;
     private final FrameHandler<C, T> frameHandler;
 
-    public ConversationContextWrapper(ConversationContext<C> delegate, Class<C> wireType, Function<C, FrameData> adapter, FrameHandler<C, T> frameHandler) {
+    private final PlcAuthentication authentication;
+
+    public ConversationContextWrapper(ConversationContext<C> delegate, Class<C> wireType, Function<C, FrameData> adapter, FrameHandler<C, T> frameHandler, PlcAuthentication authentication) {
         this.delegate = delegate;
         this.wireType = wireType;
         this.adapter = adapter;
         this.frameHandler = frameHandler;
+        this.authentication = authentication;
+    }
+
+    @Override
+    public PlcAuthentication getAuthentication() {
+        return authentication;
     }
 
     @Override
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 ad0f4f08b..11b436cd1 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
@@ -19,7 +19,6 @@
 package org.apache.plc4x.java.opcua;
 
 import org.apache.plc4x.java.api.PlcConnection;
-import org.apache.plc4x.java.api.authentication.PlcAuthentication;
 import org.apache.plc4x.java.api.exceptions.PlcConnectionException;
 import org.apache.plc4x.java.opcua.field.OpcuaField;
 import org.apache.plc4x.java.opcua.field.OpcuaPlcFieldHandler;
@@ -237,12 +236,8 @@ public class OpcuaPlcDriver extends GeneratedDriverBase<OpcuaAPU> {
             awaitDisconnectComplete,
             awaitDiscoverComplete,
             getStackConfigurer(),
-            getOptimizer());
-    }
-
-    @Override
-    public PlcConnection getConnection(String url, PlcAuthentication authentication) throws PlcConnectionException {
-        throw new PlcConnectionException("Authentication not supported.");
+            getOptimizer(),
+            null);
     }
 
     /** Estimate the Length of a Packet */
diff --git a/plc4j/drivers/simulated/src/main/java/org/apache/plc4x/java/simulated/connection/SimulatedConnection.java b/plc4j/drivers/simulated/src/main/java/org/apache/plc4x/java/simulated/connection/SimulatedConnection.java
index c580aea2c..7f429ded3 100644
--- a/plc4j/drivers/simulated/src/main/java/org/apache/plc4x/java/simulated/connection/SimulatedConnection.java
+++ b/plc4j/drivers/simulated/src/main/java/org/apache/plc4x/java/simulated/connection/SimulatedConnection.java
@@ -78,7 +78,8 @@ public class SimulatedConnection extends AbstractPlcConnection implements PlcRea
     private final Map<Integer, Consumer<PlcSubscriptionEvent>> consumerIdMap = new ConcurrentHashMap<>();
 
     public SimulatedConnection(SimulatedDevice device) {
-        super(true, true, true, false, new SimulatedFieldHandler(), new IEC61131ValueHandler(), null);
+        super(true, true, true, false,
+            new SimulatedFieldHandler(), new IEC61131ValueHandler(), null, null);
         this.device = device;
     }
 
diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/ConversationContext.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/ConversationContext.java
index 568ecf0d9..94b09a282 100644
--- a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/ConversationContext.java
+++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/ConversationContext.java
@@ -19,6 +19,7 @@
 package org.apache.plc4x.java.spi;
 
 import io.netty.channel.Channel;
+import org.apache.plc4x.java.api.authentication.PlcAuthentication;
 import org.apache.plc4x.java.api.exceptions.PlcRuntimeException;
 import org.apache.plc4x.java.spi.configuration.Configuration;
 
@@ -31,6 +32,8 @@ import java.util.function.Predicate;
 
 public interface ConversationContext<T> {
 
+    PlcAuthentication getAuthentication();
+
     Channel getChannel();
 
     boolean isPassive();
diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/Plc4xNettyWrapper.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/Plc4xNettyWrapper.java
index b9f8d0811..33ef31667 100644
--- a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/Plc4xNettyWrapper.java
+++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/Plc4xNettyWrapper.java
@@ -23,6 +23,7 @@ import io.netty.channel.ChannelHandlerContext;
 import io.netty.channel.ChannelPipeline;
 import io.netty.handler.codec.MessageToMessageCodec;
 import io.vavr.control.Either;
+import org.apache.plc4x.java.api.authentication.PlcAuthentication;
 import org.apache.plc4x.java.spi.configuration.Configuration;
 import org.apache.plc4x.java.spi.events.*;
 import org.apache.plc4x.java.spi.internal.DefaultExpectRequestContext;
@@ -48,17 +49,28 @@ public class Plc4xNettyWrapper<T> extends MessageToMessageCodec<T, Object> {
     private static final Logger logger = LoggerFactory.getLogger(Plc4xNettyWrapper.class);
 
     private final Plc4xProtocolBase<T> protocolBase;
+
+    private final PlcAuthentication authentication;
+
     private final Queue<HandlerRegistration> registeredHandlers;
     private final ChannelPipeline pipeline;
     private final boolean passive;
 
-    public Plc4xNettyWrapper(ChannelPipeline pipeline, boolean passive, Plc4xProtocolBase<T> protocol, Class<T> clazz) {
+    public Plc4xNettyWrapper(ChannelPipeline pipeline, boolean passive, Plc4xProtocolBase<T> protocol,
+                             PlcAuthentication authentication, Class<T> clazz) {
         super(clazz, Object.class);
         this.pipeline = pipeline;
         this.passive = passive;
         this.registeredHandlers = new ConcurrentLinkedQueue<>();
         this.protocolBase = protocol;
+        this.authentication = authentication;
         this.protocolBase.setContext(new ConversationContext<T>() {
+
+            @Override
+            public PlcAuthentication getAuthentication() {
+                return authentication;
+            }
+
             @Override
             public Channel getChannel() {
                 return pipeline.channel();
@@ -179,7 +191,7 @@ public class Plc4xNettyWrapper<T> extends MessageToMessageCodec<T, Object> {
             }
         }
         logger.trace("None of {} registered handlers could handle message {}, using default decode method", this.registeredHandlers.size(), t);
-        protocolBase.decode(new DefaultConversationContext<>(channelHandlerContext, passive), t);
+        protocolBase.decode(new DefaultConversationContext<>(channelHandlerContext, authentication, passive), t);
     }
 
     @Override
@@ -188,13 +200,13 @@ public class Plc4xNettyWrapper<T> extends MessageToMessageCodec<T, Object> {
         // by sending a connection request to the plc.
         logger.debug("User Event triggered {}", evt);
         if (evt instanceof ConnectEvent) {
-            this.protocolBase.onConnect(new DefaultConversationContext<>(ctx, passive));
+            this.protocolBase.onConnect(new DefaultConversationContext<>(ctx, authentication, passive));
         } else if (evt instanceof DisconnectEvent) {
-            this.protocolBase.onDisconnect(new DefaultConversationContext<>(ctx, passive));
+            this.protocolBase.onDisconnect(new DefaultConversationContext<>(ctx, authentication, passive));
         } else if (evt instanceof DiscoverEvent) {
-            this.protocolBase.onDiscover(new DefaultConversationContext<>(ctx, passive));
+            this.protocolBase.onDiscover(new DefaultConversationContext<>(ctx, authentication, passive));
         } else if (evt instanceof CloseConnectionEvent) {
-            this.protocolBase.close(new DefaultConversationContext<>(ctx, passive));
+            this.protocolBase.close(new DefaultConversationContext<>(ctx, authentication, passive));
         } else {
             super.userEventTriggered(ctx, evt);
         }
@@ -202,10 +214,15 @@ public class Plc4xNettyWrapper<T> extends MessageToMessageCodec<T, Object> {
 
     public class DefaultConversationContext<T1> implements ConversationContext<T1> {
         private final ChannelHandlerContext channelHandlerContext;
+
+        private final PlcAuthentication authentication;
         private final boolean passive;
 
-        public DefaultConversationContext(ChannelHandlerContext channelHandlerContext, boolean passive) {
+        public DefaultConversationContext(ChannelHandlerContext channelHandlerContext,
+                                          PlcAuthentication authentication,
+                                          boolean passive) {
             this.channelHandlerContext = channelHandlerContext;
+            this.authentication = authentication;
             this.passive = passive;
         }
 
@@ -214,6 +231,10 @@ public class Plc4xNettyWrapper<T> extends MessageToMessageCodec<T, Object> {
             return channelHandlerContext.channel();
         }
 
+        public PlcAuthentication getAuthentication() {
+            return authentication;
+        }
+
         @Override
         public boolean isPassive() {
             return passive;
diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/connection/AbstractPlcConnection.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/connection/AbstractPlcConnection.java
index 78a1eb809..bf9451818 100644
--- a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/connection/AbstractPlcConnection.java
+++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/connection/AbstractPlcConnection.java
@@ -20,6 +20,7 @@ package org.apache.plc4x.java.spi.connection;
 
 import org.apache.commons.lang3.NotImplementedException;
 import org.apache.plc4x.java.api.PlcConnection;
+import org.apache.plc4x.java.api.authentication.PlcAuthentication;
 import org.apache.plc4x.java.api.exceptions.PlcUnsupportedOperationException;
 import org.apache.plc4x.java.api.messages.*;
 import org.apache.plc4x.java.api.metadata.PlcConnectionMetadata;
@@ -50,6 +51,7 @@ public abstract class AbstractPlcConnection implements PlcConnection, PlcConnect
     private PlcValueHandler valueHandler;
     private Plc4xProtocolBase<?> protocol;
     private BaseOptimizer optimizer;
+    private PlcAuthentication authentication;
 
     /**
      * @deprecated only for compatibility reasons.
@@ -58,8 +60,9 @@ public abstract class AbstractPlcConnection implements PlcConnection, PlcConnect
     protected AbstractPlcConnection() {
     }
 
-    protected AbstractPlcConnection(boolean canRead, boolean canWrite, boolean canSubscribe, boolean canBrowse, PlcFieldHandler fieldHandler, PlcValueHandler valueHandler,
-                                 BaseOptimizer optimizer) {
+    protected AbstractPlcConnection(boolean canRead, boolean canWrite, boolean canSubscribe, boolean canBrowse,
+                                    PlcFieldHandler fieldHandler, PlcValueHandler valueHandler,
+                                    BaseOptimizer optimizer, PlcAuthentication authentication) {
         this.canRead = canRead;
         this.canWrite = canWrite;
         this.canSubscribe = canSubscribe;
@@ -67,6 +70,7 @@ public abstract class AbstractPlcConnection implements PlcConnection, PlcConnect
         this.fieldHandler = fieldHandler;
         this.valueHandler = valueHandler;
         this.optimizer = optimizer;
+        this.authentication = authentication;
     }
 
     public void setProtocol(Plc4xProtocolBase<?> protocol) {
@@ -113,6 +117,10 @@ public abstract class AbstractPlcConnection implements PlcConnection, PlcConnect
         return this.valueHandler;
     }
 
+    protected PlcAuthentication getAuthentication() {
+        return authentication;
+    }
+
     @Override
     public PlcReadRequest.Builder readRequestBuilder() {
         if (!canRead()) {
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 01278fc7f..395a029d3 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
@@ -25,6 +25,7 @@ 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.authentication.PlcAuthentication;
 import org.apache.plc4x.java.api.listener.EventListener;
 import org.apache.plc4x.java.spi.Plc4xNettyWrapper;
 import org.apache.plc4x.java.spi.Plc4xProtocolBase;
@@ -52,6 +53,7 @@ public class CustomProtocolStackConfigurer<BASE_PACKET_CLASS extends Message> im
     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) {
@@ -87,8 +89,9 @@ public class CustomProtocolStackConfigurer<BASE_PACKET_CLASS extends Message> im
 
     /** Applies the given Stack to the Pipeline */
     @Override
-    public Plc4xProtocolBase<BASE_PACKET_CLASS> configurePipeline(
-        Configuration configuration, ChannelPipeline pipeline, boolean passive, List<EventListener> ignore) {
+    public Plc4xProtocolBase<BASE_PACKET_CLASS> configurePipeline(Configuration configuration, ChannelPipeline pipeline,
+                                                                  PlcAuthentication authentication, boolean passive,
+                                                                  List<EventListener> ignore) {
         if (this.encryptionHandler != null) {
             pipeline.addLast(this.encryptionHandler);
         }
@@ -98,7 +101,7 @@ public class CustomProtocolStackConfigurer<BASE_PACKET_CLASS extends Message> im
         if (driverContext != null) {
             protocol.setDriverContext(driverContext);
         }
-        Plc4xNettyWrapper<BASE_PACKET_CLASS> context = new Plc4xNettyWrapper<>(pipeline, passive, protocol, basePacketClass);
+        Plc4xNettyWrapper<BASE_PACKET_CLASS> context = new Plc4xNettyWrapper<>(pipeline, passive, protocol, authentication, basePacketClass);
         pipeline.addLast(context);
         return protocol;
     }
@@ -173,7 +176,8 @@ public class CustomProtocolStackConfigurer<BASE_PACKET_CLASS extends Message> im
         public CustomProtocolStackConfigurer<BASE_PACKET_CLASS> build() {
             assert this.protocol != null;
             return new CustomProtocolStackConfigurer<>(
-                basePacketClass, byteOrder, parserArgs, protocol, driverContext, messageInput, packetSizeEstimator, corruptPacketRemover, encryptionHandler);
+                basePacketClass, byteOrder, parserArgs, protocol, driverContext, messageInput, packetSizeEstimator,
+                corruptPacketRemover, encryptionHandler);
         }
 
     }
diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/connection/DefaultNettyPlcConnection.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/connection/DefaultNettyPlcConnection.java
index 303465976..f52541b5e 100644
--- a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/connection/DefaultNettyPlcConnection.java
+++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/connection/DefaultNettyPlcConnection.java
@@ -22,6 +22,7 @@ import io.netty.channel.*;
 import io.netty.util.HashedWheelTimer;
 import io.netty.util.Timer;
 import org.apache.plc4x.java.api.EventPlcConnection;
+import org.apache.plc4x.java.api.authentication.PlcAuthentication;
 import org.apache.plc4x.java.api.exceptions.PlcConnectionException;
 import org.apache.plc4x.java.api.exceptions.PlcIoException;
 import org.apache.plc4x.java.api.listener.ConnectionStateListener;
@@ -33,7 +34,6 @@ import org.apache.plc4x.java.spi.events.*;
 import org.apache.plc4x.java.spi.optimizer.BaseOptimizer;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-import org.apache.plc4x.java.api.value.PlcValueHandler;
 
 import java.util.List;
 import java.util.concurrent.CompletableFuture;
@@ -54,6 +54,7 @@ public class DefaultNettyPlcConnection extends AbstractPlcConnection implements
 
     protected final Configuration configuration;
     protected final ChannelFactory channelFactory;
+
     protected final boolean awaitSessionSetupComplete;
     protected final boolean awaitSessionDisconnectComplete;
     protected final boolean awaitSessionDiscoverComplete;
@@ -68,8 +69,9 @@ public class DefaultNettyPlcConnection extends AbstractPlcConnection implements
                                      PlcFieldHandler fieldHandler, PlcValueHandler valueHandler, Configuration configuration,
                                      ChannelFactory channelFactory, boolean awaitSessionSetupComplete,
                                      boolean awaitSessionDisconnectComplete, boolean awaitSessionDiscoverComplete,
-                                     ProtocolStackConfigurer stackConfigurer, BaseOptimizer optimizer) {
-        super(canRead, canWrite, canSubscribe, canBrowse, fieldHandler, valueHandler, optimizer);
+                                     ProtocolStackConfigurer stackConfigurer, BaseOptimizer optimizer,
+                                     PlcAuthentication authentication) {
+        super(canRead, canWrite, canSubscribe, canBrowse, fieldHandler, valueHandler, optimizer, authentication);
         this.configuration = configuration;
         this.channelFactory = channelFactory;
         this.awaitSessionSetupComplete = awaitSessionSetupComplete;
@@ -220,7 +222,8 @@ public class DefaultNettyPlcConnection extends AbstractPlcConnection implements
                 // Initialize via Transport Layer
                 channelFactory.initializePipeline(pipeline);
                 // Initialize Protocol Layer
-                setProtocol(stackConfigurer.configurePipeline(configuration, pipeline, channelFactory.isPassive()));
+                setProtocol(stackConfigurer.configurePipeline(configuration, pipeline, getAuthentication(),
+                    channelFactory.isPassive()));
             }
         };
     }
diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/connection/GeneratedDriverBase.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/connection/GeneratedDriverBase.java
index 7c65760ac..428f2b73c 100644
--- a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/connection/GeneratedDriverBase.java
+++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/connection/GeneratedDriverBase.java
@@ -96,6 +96,11 @@ public abstract class GeneratedDriverBase<BASE_PACKET extends Message> implement
 
     @Override
     public PlcConnection getConnection(String connectionString) throws PlcConnectionException {
+        return getConnection(connectionString, null);
+    }
+
+    @Override
+    public PlcConnection getConnection(String connectionString, PlcAuthentication authentication) throws PlcConnectionException {
         // Split up the connection string into its individual segments.
         Matcher matcher = URI_PATTERN.matcher(connectionString);
         if (!matcher.matches()) {
@@ -122,7 +127,7 @@ public abstract class GeneratedDriverBase<BASE_PACKET extends Message> implement
             throw new PlcConnectionException("Unsupported configuration");
         }
 
-        // Try to find a transport in order to create a communication channel.
+        // Try to find a suitable transport-type for creating the communication channel.
         Transport transport = null;
         ServiceLoader<Transport> transportLoader = ServiceLoader.load(
             Transport.class, Thread.currentThread().getContextClassLoader());
@@ -177,12 +182,8 @@ public abstract class GeneratedDriverBase<BASE_PACKET extends Message> implement
             awaitDisconnectComplete,
             awaitDiscoverComplete,
             getStackConfigurer(transport),
-            getOptimizer());
-    }
-
-    @Override
-    public PlcConnection getConnection(String url, PlcAuthentication authentication) throws PlcConnectionException {
-        throw new PlcConnectionException("Authentication not supported.");
+            getOptimizer(),
+            authentication);
     }
 
 
diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/connection/NettyChannelFactory.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/connection/NettyChannelFactory.java
index 4f9adcb2c..8c9d6f912 100644
--- a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/connection/NettyChannelFactory.java
+++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/connection/NettyChannelFactory.java
@@ -84,7 +84,7 @@ public abstract class NettyChannelFactory implements ChannelFactory {
      * otherwise a Runtime Exception will be produced by Netty
      * <p>
      * By Default Nettys {@link NioEventLoopGroup} is used.
-     * Transports which have to use a different EventLoopGroup have to override {@link #getEventLoopGroup()}.
+     * Transports which have to use a different EventLoopGroup have to override {#getEventLoopGroup()}.
      */
     public EventLoopGroup getEventLoopGroup() {
         return new NioEventLoopGroup();
@@ -117,12 +117,11 @@ public abstract class NettyChannelFactory implements ChannelFactory {
             });
 
             final Channel channel = f.channel();
-            
-            // Shutdowm the workerGroup when channel closing to avoid open too many files
-            channel.closeFuture().addListener(future -> workerGroup.shutdownGracefully());
 
-            // Add to event-loop group
             if (workerGroup != null) {
+                // Shut down the workerGroup when channel closing to avoid open too many files
+                channel.closeFuture().addListener(future -> workerGroup.shutdownGracefully());
+                // Add to event-loop group
                 eventLoops.put(channel, workerGroup);
             }
 
diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/connection/ProtocolStackConfigurer.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/connection/ProtocolStackConfigurer.java
index c98c792fa..c89a29c35 100644
--- a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/connection/ProtocolStackConfigurer.java
+++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/connection/ProtocolStackConfigurer.java
@@ -19,21 +19,21 @@
 package org.apache.plc4x.java.spi.connection;
 
 import io.netty.channel.ChannelPipeline;
+import org.apache.plc4x.java.api.authentication.PlcAuthentication;
 import org.apache.plc4x.java.api.listener.EventListener;
 import org.apache.plc4x.java.spi.Plc4xProtocolBase;
 import org.apache.plc4x.java.spi.configuration.Configuration;
 import org.apache.plc4x.java.spi.generation.Message;
 
-import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 
 public interface ProtocolStackConfigurer<T extends Message> {
 
-    default Plc4xProtocolBase<T> configurePipeline(Configuration configuration, ChannelPipeline pipeline, boolean passive) {
-        return configurePipeline(configuration, pipeline, passive, Collections.emptyList());
+    default Plc4xProtocolBase<T> configurePipeline(Configuration configuration, ChannelPipeline pipeline, PlcAuthentication authentication, boolean passive) {
+        return configurePipeline(configuration, pipeline, authentication, passive, Collections.emptyList());
     }
 
-    Plc4xProtocolBase<T> configurePipeline(Configuration configuration, ChannelPipeline pipeline, boolean passive, List<EventListener> listeners);
+    Plc4xProtocolBase<T> configurePipeline(Configuration configuration, ChannelPipeline pipeline, PlcAuthentication authentication, boolean passive, List<EventListener> listeners);
 
 }
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 4cc75168c..8c60e5262 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
@@ -24,6 +24,7 @@ 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.authentication.PlcAuthentication;
 import org.apache.plc4x.java.api.exceptions.PlcRuntimeException;
 import org.apache.plc4x.java.api.listener.EventListener;
 import org.apache.plc4x.java.spi.Plc4xNettyWrapper;
@@ -99,8 +100,9 @@ public class SingleProtocolStackConfigurer<BASE_PACKET_CLASS extends Message> im
      * Applies the given Stack to the Pipeline
      */
     @Override
-    public Plc4xProtocolBase<BASE_PACKET_CLASS> configurePipeline(
-        Configuration configuration, ChannelPipeline pipeline, boolean passive, List<EventListener> ignore) {
+    public Plc4xProtocolBase<BASE_PACKET_CLASS> configurePipeline(Configuration configuration, ChannelPipeline pipeline,
+                                                                  PlcAuthentication authentication, boolean passive,
+                                                                  List<EventListener> ignore) {
         if (this.encryptionHandler != null) {
             pipeline.addLast(this.encryptionHandler);
         }
@@ -109,7 +111,8 @@ public class SingleProtocolStackConfigurer<BASE_PACKET_CLASS extends Message> im
         if (driverContextClass != null) {
             protocol.setDriverContext(configure(configuration, createInstance(driverContextClass)));
         }
-        Plc4xNettyWrapper<BASE_PACKET_CLASS> context = new Plc4xNettyWrapper<>(pipeline, passive, protocol, basePacketClass);
+        Plc4xNettyWrapper<BASE_PACKET_CLASS> context = new Plc4xNettyWrapper<>(pipeline, passive, protocol,
+            authentication, basePacketClass);
         pipeline.addLast(context);
         return protocol;
     }
@@ -197,7 +200,9 @@ public class SingleProtocolStackConfigurer<BASE_PACKET_CLASS extends Message> im
 
         public SingleProtocolStackConfigurer<BASE_PACKET_CLASS> build() {
             assert this.protocol != null;
-            return new SingleProtocolStackConfigurer<>(basePacketClass, byteOrder, parserArgs, protocol, driverContextClass, messageInput, messageOutput, packetSizeEstimator, corruptPacketRemover, encryptionHandler);
+            return new SingleProtocolStackConfigurer<>(basePacketClass, byteOrder, parserArgs, protocol,
+                driverContextClass, messageInput, messageOutput, packetSizeEstimator, corruptPacketRemover,
+                encryptionHandler);
         }
 
     }
diff --git a/plc4j/spi/src/test/java/org/apache/plc4x/java/spi/Plc4xNettyWrapperTest.java b/plc4j/spi/src/test/java/org/apache/plc4x/java/spi/Plc4xNettyWrapperTest.java
index 95b13cbf6..3b360c3b9 100644
--- a/plc4j/spi/src/test/java/org/apache/plc4x/java/spi/Plc4xNettyWrapperTest.java
+++ b/plc4j/spi/src/test/java/org/apache/plc4x/java/spi/Plc4xNettyWrapperTest.java
@@ -59,7 +59,7 @@ class Plc4xNettyWrapperTest {
 
     @BeforeEach
     void setUp() throws Exception {
-        wrapper = new Plc4xNettyWrapper<>(channelPipeline, false, protocol, Date.class);
+        wrapper = new Plc4xNettyWrapper<>(channelPipeline, false, protocol, null, Date.class);
 
         ArgumentCaptor<ConversationContext<Date>> captor = ArgumentCaptor.forClass(ConversationContext.class);
         doNothing().when(protocol).onConnect(captor.capture());
diff --git a/sandbox/test-java-df1-driver/src/main/java/org/apache/plc4x/java/df1/DF1PlcDriver.java b/sandbox/test-java-df1-driver/src/main/java/org/apache/plc4x/java/df1/DF1PlcDriver.java
index 8095f1ccb..2f1baded9 100644
--- a/sandbox/test-java-df1-driver/src/main/java/org/apache/plc4x/java/df1/DF1PlcDriver.java
+++ b/sandbox/test-java-df1-driver/src/main/java/org/apache/plc4x/java/df1/DF1PlcDriver.java
@@ -18,7 +18,6 @@
  */
 package org.apache.plc4x.java.df1;
 
-import org.apache.plc4x.java.api.PlcDriver;
 import org.apache.plc4x.java.api.value.PlcValueHandler;
 import org.apache.plc4x.java.df1.configuration.Df1Configuration;
 import org.apache.plc4x.java.df1.field.Df1FieldHandler;


[plc4x] 03/03: fix(plc4j/ads): Implemented the automatic adding of AMS routes in Beckhoff PLCs

Posted by cd...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

cdutz pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/plc4x.git

commit 6e6507ba52614741539389619705c2fba545f3ba
Author: Christofer Dutz <ch...@c-ware.de>
AuthorDate: Tue Aug 30 21:54:43 2022 +0200

    fix(plc4j/ads): Implemented the automatic adding of AMS routes in Beckhoff PLCs
---
 plc4j/drivers/ads/pom.xml                          |  4 ++
 .../plc4x/java/ads/protocol/AdsProtocolLogic.java  | 75 ++++++++++++++++++++++
 2 files changed, 79 insertions(+)

diff --git a/plc4j/drivers/ads/pom.xml b/plc4j/drivers/ads/pom.xml
index 3f673c500..483440b1e 100644
--- a/plc4j/drivers/ads/pom.xml
+++ b/plc4j/drivers/ads/pom.xml
@@ -149,6 +149,10 @@
       <groupId>io.netty</groupId>
       <artifactId>netty-buffer</artifactId>
     </dependency>
+    <dependency>
+      <groupId>io.netty</groupId>
+      <artifactId>netty-transport</artifactId>
+    </dependency>
     <dependency>
       <groupId>org.apache.commons</groupId>
       <artifactId>commons-lang3</artifactId>
diff --git a/plc4j/drivers/ads/src/main/java/org/apache/plc4x/java/ads/protocol/AdsProtocolLogic.java b/plc4j/drivers/ads/src/main/java/org/apache/plc4x/java/ads/protocol/AdsProtocolLogic.java
index 58e065e5f..4f905e39c 100644
--- a/plc4j/drivers/ads/src/main/java/org/apache/plc4x/java/ads/protocol/AdsProtocolLogic.java
+++ b/plc4j/drivers/ads/src/main/java/org/apache/plc4x/java/ads/protocol/AdsProtocolLogic.java
@@ -19,10 +19,14 @@
 package org.apache.plc4x.java.ads.protocol;
 
 import org.apache.plc4x.java.ads.configuration.AdsConfiguration;
+import org.apache.plc4x.java.ads.discovery.readwrite.*;
+import org.apache.plc4x.java.ads.discovery.readwrite.AmsNetId;
 import org.apache.plc4x.java.ads.field.*;
 import org.apache.plc4x.java.ads.model.AdsSubscriptionHandle;
 import org.apache.plc4x.java.ads.readwrite.*;
 import org.apache.plc4x.java.ads.readwrite.DataItem;
+import org.apache.plc4x.java.api.authentication.PlcUsernamePasswordAuthentication;
+import org.apache.plc4x.java.api.exceptions.PlcConnectionException;
 import org.apache.plc4x.java.api.exceptions.PlcException;
 import org.apache.plc4x.java.api.exceptions.PlcRuntimeException;
 import org.apache.plc4x.java.api.messages.*;
@@ -46,6 +50,7 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import java.math.BigInteger;
+import java.net.*;
 import java.time.Duration;
 import java.time.Instant;
 import java.util.*;
@@ -102,6 +107,76 @@ public class AdsProtocolLogic extends Plc4xProtocolBase<AmsTCPPacket> implements
         LOGGER.debug("Fetching sizes of symbol and datatype table sizes.");
         final CompletableFuture<Void> future = new CompletableFuture<>();
 
+        // If we have connection credentials available, try to set up the AMS routes.
+        if(context.getAuthentication() != null) {
+            if(!(context.getAuthentication() instanceof PlcUsernamePasswordAuthentication)) {
+                future.completeExceptionally(new PlcConnectionException(
+                    "This type of connection only supports username-password authentication"));
+                return;
+            }
+            PlcUsernamePasswordAuthentication usernamePasswordAuthentication =
+                (PlcUsernamePasswordAuthentication) context.getAuthentication();
+
+            // Prepre the request message.
+            org.apache.plc4x.java.ads.discovery.readwrite.AmsNetId sourceAmsNetId = new AmsNetId(
+                configuration.getSourceAmsNetId().getOctet1(), configuration.getSourceAmsNetId().getOctet2(),
+                configuration.getSourceAmsNetId().getOctet3(), configuration.getSourceAmsNetId().getOctet4(),
+                configuration.getSourceAmsNetId().getOctet5(), configuration.getSourceAmsNetId().getOctet6());
+            String routeName = String.format("PLC4X-%d.%d.%d.%d.%d.%d",
+                sourceAmsNetId.getOctet1(), sourceAmsNetId.getOctet2(), sourceAmsNetId.getOctet3(),
+                sourceAmsNetId.getOctet4(), sourceAmsNetId.getOctet5(), sourceAmsNetId.getOctet6());
+            AdsDiscovery addOrUpdateRouteRequest = new AdsDiscovery(getInvokeId(), Operation.ADD_OR_UPDATE_ROUTE_REQUEST,
+                sourceAmsNetId, AdsPortNumbers.SYSTEM_SERVICE,
+                Arrays.asList(new AdsDiscoveryBlockRouteName(new AmsString(routeName)),
+                    new AdsDiscoveryBlockAmsNetId(sourceAmsNetId),
+                    new AdsDiscoveryBlockUserName(new AmsString(usernamePasswordAuthentication.getUsername())),
+                    new AdsDiscoveryBlockPassword(new AmsString(usernamePasswordAuthentication.getPassword())),
+                    new AdsDiscoveryBlockHostName(new AmsString("host-name-or-ip"))));
+
+            // Send the request to the PLC using a UDP socket.
+            try (DatagramSocket adsDiscoverySocket = new DatagramSocket(AdsDiscoveryConstants.ADSDISCOVERYUDPDEFAULTPORT)) {
+                // Serialize the message.
+                WriteBufferByteBased writeBuffer = new WriteBufferByteBased(
+                    addOrUpdateRouteRequest.getLengthInBytes(), ByteOrder.LITTLE_ENDIAN);
+                addOrUpdateRouteRequest.serialize(writeBuffer);
+
+                // Get the target IP from the connection
+                SocketAddress remoteSocketAddress = context.getChannel().remoteAddress();
+                InetAddress remoteAddress = ((InetSocketAddress) remoteSocketAddress).getAddress();
+
+                // Create the UDP packet to the broadcast address.
+                DatagramPacket discoveryRequestPacket = new DatagramPacket(
+                    writeBuffer.getBytes(), writeBuffer.getBytes().length,
+                    remoteAddress, AdsDiscoveryConstants.ADSDISCOVERYUDPDEFAULTPORT);
+                adsDiscoverySocket.send(discoveryRequestPacket);
+
+                // The actual length would be 32, but better be prepared for a more verbose response
+                byte[] buf = new byte[100];
+                DatagramPacket responsePacket = new DatagramPacket(buf, buf.length);
+                adsDiscoverySocket.setSoTimeout(configuration.getTimeoutRequest());
+                adsDiscoverySocket.receive(responsePacket);
+
+                // Receive the response
+                ReadBufferByteBased readBuffer = new ReadBufferByteBased(responsePacket.getData(), ByteOrder.LITTLE_ENDIAN);
+                AdsDiscovery addOrUpdateRouteResponse = AdsDiscovery.staticParse(readBuffer);
+
+                // Check if adding the route was successful
+                if (addOrUpdateRouteResponse.getRequestId() == 1) {
+                    for (AdsDiscoveryBlock block : addOrUpdateRouteResponse.getBlocks()) {
+                        if(block.getBlockType() == AdsDiscoveryBlockType.STATUS) {
+                            AdsDiscoveryBlockStatus statusBlock = (AdsDiscoveryBlockStatus) block;
+                            if(statusBlock.getStatus() != Status.SUCCESS) {
+                                future.completeExceptionally(new PlcConnectionException("Error adding AMS route"));
+                                return;
+                            }
+                        }
+                    }
+                }
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+        }
+
         List<AdsDataTypeTableEntry> dataTypes = new ArrayList<>();
         List<AdsSymbolTableEntry> symbols = new ArrayList<>();
         // Initialize the request.