From: Robert Varga Date: Sun, 25 Feb 2024 10:14:28 +0000 (+0100) Subject: Split out ClientTransportChannelListener X-Git-Tag: v7.0.0~15 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=commitdiff_plain;h=4dbeb7b2bca6f7c8297d4211560c6f581a505678;p=netconf.git Split out ClientTransportChannelListener 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 --- 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 index 0000000000..bf4efad70d --- /dev/null +++ b/protocol/netconf-client/src/main/java/org/opendaylight/netconf/client/ClientTransportChannelListener.java @@ -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 sessionFuture = SettableFuture.create(); + private final ClientChannelInitializer initializer; + + ClientTransportChannelListener(final ClientChannelInitializer initializer) { + this.initializer = requireNonNull(initializer); + } + + @NonNull ListenableFuture sessionFuture() { + return sessionFuture; + } + + @Override + public void onTransportChannelEstablished(final TransportChannel channel) { + final var nettyChannel = channel.channel(); + final var promise = nettyChannel.eventLoop().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 diff --git a/protocol/netconf-client/src/main/java/org/opendaylight/netconf/client/NetconfClientFactoryImpl.java b/protocol/netconf-client/src/main/java/org/opendaylight/netconf/client/NetconfClientFactoryImpl.java index 73244e8011..940da73b68 100644 --- a/protocol/netconf-client/src/main/java/org/opendaylight/netconf/client/NetconfClientFactoryImpl.java +++ b/protocol/netconf-client/src/main/java/org/opendaylight/netconf/client/NetconfClientFactoryImpl.java @@ -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 createClient(final NetconfClientConfiguration configuration) throws UnsupportedConfigurationException { - final var future = SettableFuture.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 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().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); - } - } }