Split out ClientTransportChannelListener 37/110337/3
authorRobert Varga <robert.varga@pantheon.tech>
Sun, 25 Feb 2024 10:14:28 +0000 (11:14 +0100)
committerRobert Varga <nite@hq.sk>
Sun, 25 Feb 2024 11:05:05 +0000 (11:05 +0000)
Promote this record to a top-level class, so that it can be tested
easily.

While we are at it, allocate it in a single place and make sure we do
not retain a reference to configuration.

JIRA: NETCONF-590
Change-Id: I8eace1bd10ed6f2810d9bc85020d843f2558bcde
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
protocol/netconf-client/src/main/java/org/opendaylight/netconf/client/ClientTransportChannelListener.java [new file with mode: 0644]
protocol/netconf-client/src/main/java/org/opendaylight/netconf/client/NetconfClientFactoryImpl.java

diff --git a/protocol/netconf-client/src/main/java/org/opendaylight/netconf/client/ClientTransportChannelListener.java b/protocol/netconf-client/src/main/java/org/opendaylight/netconf/client/ClientTransportChannelListener.java
new file mode 100644 (file)
index 0000000..bf4efad
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2024 PANTHEON.tech, s.r.o. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.netconf.client;
+
+import static java.util.Objects.requireNonNull;
+
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.SettableFuture;
+import org.eclipse.jdt.annotation.NonNull;
+import org.opendaylight.netconf.transport.api.TransportChannel;
+import org.opendaylight.netconf.transport.api.TransportChannelListener;
+
+final class ClientTransportChannelListener implements TransportChannelListener {
+    private final @NonNull SettableFuture<NetconfClientSession> sessionFuture = SettableFuture.create();
+    private final ClientChannelInitializer initializer;
+
+    ClientTransportChannelListener(final ClientChannelInitializer initializer) {
+        this.initializer = requireNonNull(initializer);
+    }
+
+    @NonNull ListenableFuture<NetconfClientSession> sessionFuture() {
+        return sessionFuture;
+    }
+
+    @Override
+    public void onTransportChannelEstablished(final TransportChannel channel) {
+        final var nettyChannel = channel.channel();
+        final var promise = nettyChannel.eventLoop().<NetconfClientSession>newPromise();
+        initializer.initialize(nettyChannel, promise);
+        promise.addListener(ignored -> {
+            final var cause = promise.cause();
+            if (cause != null) {
+                sessionFuture.setException(cause);
+            } else {
+                sessionFuture.set(promise.getNow());
+            }
+        });
+    }
+
+    @Override
+    public void onTransportChannelFailed(final Throwable cause) {
+        sessionFuture.setException(cause);
+    }
+}
\ No newline at end of file
index 73244e80115b7d47322b9813aee2b34f0b1fe1ff..940da73b68ae2b736964e52dfe68cdf8573d81a7 100644 (file)
@@ -11,15 +11,13 @@ import static java.util.Objects.requireNonNull;
 
 import com.google.common.collect.ImmutableSet;
 import com.google.common.util.concurrent.ListenableFuture;
-import com.google.common.util.concurrent.SettableFuture;
 import javax.annotation.PreDestroy;
 import javax.inject.Inject;
 import javax.inject.Singleton;
+import org.eclipse.jdt.annotation.NonNull;
 import org.opendaylight.netconf.api.TransportConstants;
 import org.opendaylight.netconf.client.conf.NetconfClientConfiguration;
 import org.opendaylight.netconf.common.NetconfTimer;
-import org.opendaylight.netconf.transport.api.TransportChannel;
-import org.opendaylight.netconf.transport.api.TransportChannelListener;
 import org.opendaylight.netconf.transport.api.UnsupportedConfigurationException;
 import org.opendaylight.netconf.transport.ssh.SSHTransportStackFactory;
 import org.opendaylight.netconf.transport.tcp.TCPClient;
@@ -63,32 +61,29 @@ public final class NetconfClientFactoryImpl implements NetconfClientFactory {
     @Override
     public ListenableFuture<NetconfClientSession> createClient(final NetconfClientConfiguration configuration)
             throws UnsupportedConfigurationException {
-        final var future = SettableFuture.<NetconfClientSession>create();
-        final var channelInitializer = new ClientChannelInitializer(createNegotiatorFactory(configuration),
-            () -> configuration.getSessionListener());
+        final var sessionListener = configuration.getSessionListener();
+        final var transportListener = new ClientTransportChannelListener(new ClientChannelInitializer(
+            createNegotiatorFactory(configuration), () -> sessionListener));
 
-        // FIXME: do not ignore this future
         final var stackFuture = switch (configuration.getProtocol()) {
-            case SSH -> factory.connectClient(TransportConstants.SSH_SUBSYSTEM,
-                new ClientTransportChannelListener(future, channelInitializer), configuration.getTcpParameters(),
-                configuration.getSshParameters(), configuration.getSshConfigurator());
-            case TCP -> TCPClient.connect(new ClientTransportChannelListener(future, channelInitializer),
-                factory.newBootstrap(), configuration.getTcpParameters());
+            case SSH -> factory.connectClient(TransportConstants.SSH_SUBSYSTEM, transportListener,
+                configuration.getTcpParameters(), configuration.getSshParameters(), configuration.getSshConfigurator());
+            case TCP -> TCPClient.connect(transportListener, factory.newBootstrap(), configuration.getTcpParameters());
             case TLS -> {
                 var handlerFactory = configuration.getSslHandlerFactory();
                 if (handlerFactory == null) {
                     handlerFactory = new FixedSslHandlerFactory(configuration.getTlsParameters());
                 }
-                yield TLSClient.connect(new ClientTransportChannelListener(future, channelInitializer),
-                    factory.newBootstrap(), configuration.getTcpParameters(), handlerFactory);
+                yield TLSClient.connect(transportListener, factory.newBootstrap(), configuration.getTcpParameters(),
+                    handlerFactory);
             }
         };
         LOG.trace("Future stack is {}", stackFuture);
 
-        return future;
+        return transportListener.sessionFuture();
     }
 
-    private NetconfClientSessionNegotiatorFactory createNegotiatorFactory(
+    private @NonNull NetconfClientSessionNegotiatorFactory createNegotiatorFactory(
             final NetconfClientConfiguration configuration) {
         final var capabilities = configuration.getOdlHelloCapabilities();
         if (capabilities == null || capabilities.isEmpty()) {
@@ -100,33 +95,4 @@ public final class NetconfClientFactoryImpl implements NetconfClientFactory {
         return new NetconfClientSessionNegotiatorFactory(timer, configuration.getAdditionalHeader(),
             configuration.getConnectionTimeoutMillis(), stringCapabilities);
     }
-
-    private record ClientTransportChannelListener(
-            SettableFuture<NetconfClientSession> future,
-            ClientChannelInitializer initializer) implements TransportChannelListener {
-        ClientTransportChannelListener {
-            requireNonNull(future);
-            requireNonNull(initializer);
-        }
-
-        @Override
-        public void onTransportChannelEstablished(final TransportChannel channel) {
-            final var nettyChannel = channel.channel();
-            final var promise = nettyChannel.eventLoop().<NetconfClientSession>newPromise();
-            initializer.initialize(nettyChannel, promise);
-            promise.addListener(ignored -> {
-                final var cause = promise.cause();
-                if (cause != null) {
-                    future.setException(cause);
-                } else {
-                    future.set(promise.getNow());
-                }
-            });
-        }
-
-        @Override
-        public void onTransportChannelFailed(final Throwable cause) {
-            future.setException(cause);
-        }
-    }
 }