import static java.util.Objects.requireNonNull;
import com.google.common.util.concurrent.ListenableFuture;
-import io.netty.bootstrap.Bootstrap;
-import io.netty.bootstrap.ServerBootstrap;
-import io.netty.channel.EventLoopGroup;
import org.eclipse.jdt.annotation.NonNull;
import org.opendaylight.netconf.shaded.sshd.netty.NettyIoServiceFactoryFactory;
-import org.opendaylight.netconf.shaded.sshd.server.subsystem.SubsystemFactory;
import org.opendaylight.netconf.transport.api.TransportChannelListener;
import org.opendaylight.netconf.transport.api.UnsupportedConfigurationException;
-import org.opendaylight.netconf.transport.tcp.NettyTransportSupport;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ssh.client.rev230417.SshClientGrouping;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ssh.server.rev230417.SshServerGrouping;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.tcp.client.rev230417.TcpClientGrouping;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.tcp.server.rev230417.TcpServerGrouping;
+import org.opendaylight.netconf.transport.tcp.BootstrapFactory;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ssh.client.rev231228.SshClientGrouping;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ssh.server.rev231228.SshServerGrouping;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.tcp.client.rev231228.TcpClientGrouping;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.tcp.server.rev231228.TcpServerGrouping;
/**
- * A factory capable of instantiating {@link SSHClient}s and {@link SSHServer}s.
+ * A {@link BootstrapFactory} additionally capable of instantiating {@link SSHClient}s and {@link SSHServer}s.
*/
-public final class SSHTransportStackFactory implements AutoCloseable {
- private final EventLoopGroup group;
- private final EventLoopGroup parentGroup;
- private final NettyIoServiceFactoryFactory ioServiceFactory;
-
- private SSHTransportStackFactory(final EventLoopGroup group, final EventLoopGroup parentGroup) {
- this.group = requireNonNull(group);
- this.parentGroup = parentGroup;
- ioServiceFactory = new NettyIoServiceFactoryFactory(group);
- }
+public final class SSHTransportStackFactory extends BootstrapFactory {
+ private final NettyIoServiceFactoryFactory ioServiceFactory = new NettyIoServiceFactoryFactory(group);
public SSHTransportStackFactory(final @NonNull String groupName, final int groupThreads) {
- this(NettyTransportSupport.newEventLoopGroup(groupName, groupThreads), null);
+ super(groupName, groupThreads);
}
public SSHTransportStackFactory(final @NonNull String groupName, final int groupThreads,
final @NonNull String parentGroupName, final int parentGroupThreads) {
- this(NettyTransportSupport.newEventLoopGroup(groupName, groupThreads),
- NettyTransportSupport.newEventLoopGroup(parentGroupName, parentGroupThreads));
+ super(groupName, groupThreads, parentGroupName, parentGroupThreads);
}
public @NonNull ListenableFuture<SSHClient> connectClient(final String subsystem,
final TransportChannelListener listener, final TcpClientGrouping connectParams,
final SshClientGrouping clientParams) throws UnsupportedConfigurationException {
- return SSHClient.of(ioServiceFactory, group, subsystem, listener, clientParams)
+ return SSHClient.of(ioServiceFactory, group, subsystem, listener, clientParams, null)
+ .connect(newBootstrap(), connectParams);
+ }
+
+ /** Builds the SSH Client and initiates connection.
+ *
+ * @param subsystem bound subsystem name
+ * @param listener client channel listener, required
+ * @param connectParams TCP transport configuration addressing server to connect, required
+ * @param clientParams SSH overlay configuration, required, should contain username
+ * @param configurator client factory manager configurator, optional
+ * @return a future producing {@link SSHClient}
+ * @throws UnsupportedConfigurationException if any of configurations is invalid or incomplete
+ * @throws NullPointerException if any of required parameters is null
+ */
+ public @NonNull ListenableFuture<SSHClient> connectClient(final String subsystem,
+ final TransportChannelListener listener, final TcpClientGrouping connectParams,
+ final SshClientGrouping clientParams, final ClientFactoryManagerConfigurator configurator)
+ throws UnsupportedConfigurationException {
+ return SSHClient.of(ioServiceFactory, group, subsystem, listener, clientParams, configurator)
.connect(newBootstrap(), connectParams);
}
public @NonNull ListenableFuture<SSHClient> listenClient(final String subsystem,
final TransportChannelListener listener, final TcpServerGrouping listenParams,
final SshClientGrouping clientParams) throws UnsupportedConfigurationException {
- return SSHClient.of(ioServiceFactory, group, subsystem, listener, clientParams)
+ return SSHClient.of(ioServiceFactory, group, subsystem, listener, clientParams, null)
.listen(newServerBootstrap(), listenParams);
}
- public @NonNull ListenableFuture<SSHServer> connectServer(final TransportChannelListener listener,
- final SubsystemFactory subsystemFactory, final TcpClientGrouping connectParams,
- final SshServerGrouping serverParams) throws UnsupportedConfigurationException {
- return SSHServer.of(ioServiceFactory, group, listener, subsystemFactory, requireNonNull(serverParams), null)
- .connect(newBootstrap(), connectParams);
+ /**
+ * Builds and starts Call-Home SSH Client.
+ *
+ * @param subsystem bound subsystem name
+ * @param listener client channel listener, required
+ * @param listenParams TCP transport configuration addressing inbound connection, required
+ * @param clientParams SSH overlay configuration, required, should contain username
+ * @param configurator client factory manager configurator, optional
+ * @return a future producing {@link SSHClient}
+ * @throws UnsupportedConfigurationException if any of configurations is invalid or incomplete
+ * @throws NullPointerException if any of required parameters is null
+ */
+ public @NonNull ListenableFuture<SSHClient> listenClient(final String subsystem,
+ final TransportChannelListener listener, final TcpServerGrouping listenParams,
+ final SshClientGrouping clientParams, final ClientFactoryManagerConfigurator configurator)
+ throws UnsupportedConfigurationException {
+ return SSHClient.of(ioServiceFactory, group, subsystem, listener, clientParams, configurator)
+ .listen(newServerBootstrap(), listenParams);
}
- public @NonNull ListenableFuture<SSHServer> listenServer(final TransportChannelListener listener,
- final SubsystemFactory subsystemFactory, final TcpServerGrouping connectParams,
+ public @NonNull ListenableFuture<SSHServer> connectServer(final String subsystem,
+ final TransportChannelListener listener, final TcpClientGrouping connectParams,
final SshServerGrouping serverParams) throws UnsupportedConfigurationException {
- return listenServer(listener, subsystemFactory, connectParams, requireNonNull(serverParams), null);
+ return SSHServer.of(ioServiceFactory, group, subsystem, listener, requireNonNull(serverParams), null)
+ .connect(newBootstrap(), connectParams);
}
/**
- * Builds and starts SSH Server.
+ * Builds and starts a Call-Home SSH Server, initiates connection to client.
*
+ * @param subsystem bound subsystem name
* @param listener server channel listener, required
- * @param subsystemFactory A {@link SubsystemFactory} for the hosted subsystem
- * @param listenParams TCP transport configuration, required
+ * @param connectParams TCP transport configuration addressing client to be connected, required
* @param serverParams SSH overlay configuration, optional if configurator is defined, required otherwise
* @param configurator server factory manager configurator, optional if serverParams is defined, required otherwise
- * @return server instance as listenable future
+ * @return a future producing {@link SSHServer}
* @throws UnsupportedConfigurationException if any of configurations is invalid or incomplete
* @throws NullPointerException if any of required parameters is null
* @throws IllegalArgumentException if both configurator and serverParams are null
*/
- public @NonNull ListenableFuture<SSHServer> listenServer(final TransportChannelListener listener,
- final SubsystemFactory subsystemFactory, final TcpServerGrouping listenParams,
+ public @NonNull ListenableFuture<SSHServer> connectServer(final String subsystem,
+ final TransportChannelListener listener, final TcpClientGrouping connectParams,
final SshServerGrouping serverParams, final ServerFactoryManagerConfigurator configurator)
- throws UnsupportedConfigurationException {
+ throws UnsupportedConfigurationException {
checkArgument(serverParams != null || configurator != null,
"Neither server parameters nor factory configurator is defined");
- return SSHServer.of(ioServiceFactory, group, listener, subsystemFactory, serverParams, configurator)
- .listen(newServerBootstrap(), listenParams);
+ return SSHServer.of(ioServiceFactory, group, subsystem, listener, serverParams, configurator)
+ .connect(newBootstrap(), connectParams);
}
- /**
- * Create a new {@link Bootstrap} based on this factory's {@link EventLoopGroup}s.
- *
- * @return A new {@link Bootstrap}
- */
- public @NonNull Bootstrap newBootstrap() {
- return NettyTransportSupport.newBootstrap().group(group);
+ public @NonNull ListenableFuture<SSHServer> listenServer(final String subsystem,
+ final TransportChannelListener listener, final TcpServerGrouping connectParams,
+ final SshServerGrouping serverParams) throws UnsupportedConfigurationException {
+ return listenServer(subsystem, listener, connectParams, requireNonNull(serverParams), null);
}
/**
- * Create a new {@link ServerBootstrap} based on this factory's {@link EventLoopGroup}s.
+ * Builds and starts SSH Server.
*
- * @return A new {@link ServerBootstrap}
+ * @param listener server channel listener, required
+ * @param subsystem bound subsystem name
+ * @param listenParams TCP transport configuration, required
+ * @param serverParams SSH overlay configuration, optional if configurator is defined, required otherwise
+ * @param configurator server factory manager configurator, optional if serverParams is defined, required otherwise
+ * @return a future producing {@link SSHServer}
+ * @throws UnsupportedConfigurationException if any of configurations is invalid or incomplete
+ * @throws NullPointerException if any of required parameters is null
+ * @throws IllegalArgumentException if both configurator and serverParams are null
*/
- public @NonNull ServerBootstrap newServerBootstrap() {
- return NettyTransportSupport.newServerBootstrap().group(parentGroup != null ? parentGroup : group, group);
- }
-
- @Override
- public void close() {
- if (parentGroup != null) {
- parentGroup.shutdownGracefully();
- }
- group.shutdownGracefully();
+ public @NonNull ListenableFuture<SSHServer> listenServer(final String subsystem,
+ final TransportChannelListener listener, final TcpServerGrouping listenParams,
+ final SshServerGrouping serverParams, final ServerFactoryManagerConfigurator configurator)
+ throws UnsupportedConfigurationException {
+ checkArgument(serverParams != null || configurator != null,
+ "Neither server parameters nor factory configurator is defined");
+ return SSHServer.of(ioServiceFactory, group, subsystem, listener, serverParams, configurator)
+ .listen(newServerBootstrap(), listenParams);
}
}