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 2901877bef3..5652882eec9 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 @@ -44,13 +44,16 @@ public abstract class NettyChannelFactory implements ChannelFactory { private final Map eventLoops = new ConcurrentHashMap<>(); - /** - * TODO should be removed together with the Constructor. - */ - private final SocketAddress address; + private final SocketAddress localAddress; + private final SocketAddress remoteAddress; + + protected NettyChannelFactory(SocketAddress remoteAddress) { + this(null, remoteAddress); + } - protected NettyChannelFactory(SocketAddress address) { - this.address = address; + protected NettyChannelFactory(SocketAddress localAddress, SocketAddress remoteAddress) { + this.localAddress = localAddress; + this.remoteAddress = remoteAddress; } /** @@ -83,7 +86,7 @@ protected Bootstrap createBootstrap() { * Has to be in accordance with {@link #getChannel()} * otherwise a Runtime Exception will be produced by Netty *

- * By Default Nettys {@link NioEventLoopGroup} is used. + * By Default Netty's {@link NioEventLoopGroup} is used. * Transports which have to use a different EventLoopGroup have to override {#getEventLoopGroup()}. */ public EventLoopGroup getEventLoopGroup() { @@ -106,7 +109,8 @@ public Channel createChannel(ChannelHandler channelHandler) throws PlcConnection configureBootstrap(bootstrap); bootstrap.handler(channelHandler); // Start the client. - final ChannelFuture f = bootstrap.connect(address); + final ChannelFuture f = (localAddress == null) ? + bootstrap.connect(remoteAddress) : bootstrap.connect(remoteAddress, localAddress); f.addListener(future -> { if (!future.isSuccess()) { logger.info("Unable to connect, shutting down worker thread."); diff --git a/plc4j/transports/udp/src/main/java/org/apache/plc4x/java/transport/udp/UdpChannelFactory.java b/plc4j/transports/udp/src/main/java/org/apache/plc4x/java/transport/udp/UdpChannelFactory.java index d13053edff0..7fc9fe2d1a4 100644 --- a/plc4j/transports/udp/src/main/java/org/apache/plc4x/java/transport/udp/UdpChannelFactory.java +++ b/plc4j/transports/udp/src/main/java/org/apache/plc4x/java/transport/udp/UdpChannelFactory.java @@ -36,8 +36,12 @@ public class UdpChannelFactory extends NettyChannelFactory implements HasConfigu private UdpTransportConfiguration configuration; - public UdpChannelFactory(SocketAddress address) { - super(address); + public UdpChannelFactory(SocketAddress remoteAddress) { + super(remoteAddress); + } + + public UdpChannelFactory(SocketAddress localAddress, SocketAddress remoteAddress) { + super(localAddress, remoteAddress); } @Override diff --git a/plc4j/transports/udp/src/main/java/org/apache/plc4x/java/transport/udp/UdpTransport.java b/plc4j/transports/udp/src/main/java/org/apache/plc4x/java/transport/udp/UdpTransport.java index 8579c70f76a..2d90a352def 100644 --- a/plc4j/transports/udp/src/main/java/org/apache/plc4x/java/transport/udp/UdpTransport.java +++ b/plc4j/transports/udp/src/main/java/org/apache/plc4x/java/transport/udp/UdpTransport.java @@ -62,20 +62,27 @@ public ChannelFactory createChannelFactory(String transportConfig) { // If the port wasn't specified, try to get a default port from the configuration. int port; + int localPort = UdpTransportConfiguration.NO_DEFAULT_PORT; if(portString != null) { port = Integer.parseInt(portString); - } else if ((configuration != null) && - (configuration.getDefaultPort() != UdpTransportConfiguration.NO_DEFAULT_PORT)) { + } else if ((configuration != null) && (configuration.getDefaultPort() != UdpTransportConfiguration.NO_DEFAULT_PORT)) { port = configuration.getDefaultPort(); } else { throw new PlcRuntimeException("No port defined"); } + if (configuration != null) { + localPort = configuration.getLocalPort(); + } // Create the fully qualified remote socket address which we should connect to. - SocketAddress address = new InetSocketAddress((ip == null) ? hostname : ip, port); + SocketAddress remoteAddress = new InetSocketAddress((ip == null) ? hostname : ip, port); + if(localPort != UdpTransportConfiguration.NO_DEFAULT_PORT) { + SocketAddress localAddress = new InetSocketAddress(localPort); + return new UdpChannelFactory(localAddress, remoteAddress); + } // Initialize the channel factory with the default socket address we want to connect to. - return new UdpChannelFactory(address); + return new UdpChannelFactory(remoteAddress); } } diff --git a/plc4j/transports/udp/src/main/java/org/apache/plc4x/java/transport/udp/UdpTransportConfiguration.java b/plc4j/transports/udp/src/main/java/org/apache/plc4x/java/transport/udp/UdpTransportConfiguration.java index 2c26fdf2f89..8d35b04fdf0 100644 --- a/plc4j/transports/udp/src/main/java/org/apache/plc4x/java/transport/udp/UdpTransportConfiguration.java +++ b/plc4j/transports/udp/src/main/java/org/apache/plc4x/java/transport/udp/UdpTransportConfiguration.java @@ -28,4 +28,13 @@ default int getDefaultPort() { return NO_DEFAULT_PORT; } + /** + * Most transports don't care about the local port, but some do. + * This option allows forcing a local port number to be used. + * @return local port number + */ + default int getLocalPort() { + return NO_DEFAULT_PORT; + } + }