2 * Copyright (c) 2023 PANTHEON.tech s.r.o. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.netconf.server;
10 import static java.util.Objects.requireNonNull;
12 import com.google.common.util.concurrent.ListenableFuture;
13 import io.netty.bootstrap.ServerBootstrap;
14 import io.netty.channel.EventLoopGroup;
15 import io.netty.util.concurrent.DefaultPromise;
16 import io.netty.util.concurrent.EventExecutor;
17 import io.netty.util.concurrent.GlobalEventExecutor;
18 import java.util.List;
19 import org.eclipse.jdt.annotation.NonNull;
20 import org.eclipse.jdt.annotation.Nullable;
21 import org.opendaylight.netconf.server.api.NetconfServerFactory;
22 import org.opendaylight.netconf.shaded.sshd.server.SshServer;
23 import org.opendaylight.netconf.transport.api.TransportChannel;
24 import org.opendaylight.netconf.transport.api.TransportChannelListener;
25 import org.opendaylight.netconf.transport.api.UnsupportedConfigurationException;
26 import org.opendaylight.netconf.transport.ssh.SSHServer;
27 import org.opendaylight.netconf.transport.ssh.ServerFactoryManagerConfigurator;
28 import org.opendaylight.netconf.transport.tcp.NettyTransportSupport;
29 import org.opendaylight.netconf.transport.tcp.TCPServer;
30 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ssh.server.rev230417.SshServerGrouping;
31 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.tcp.server.rev230417.TcpServerGrouping;
32 import org.slf4j.Logger;
33 import org.slf4j.LoggerFactory;
35 public final class NetconfServerFactoryImpl implements NetconfServerFactory {
36 private static final Logger LOG = LoggerFactory.getLogger(NetconfServerFactoryImpl.class);
37 private static final TransportChannelListener EMPTY_LISTENER = new ChannelInitializerListener(null, null);
39 private final EventLoopGroup parentGroup;
40 private final EventLoopGroup workerGroup;
41 private final ServerChannelInitializer channelInitializer;
42 private final TransportChannelListener transportChannelListener;
44 public NetconfServerFactoryImpl(final ServerChannelInitializer channelInitializer, final EventLoopGroup bossGroup,
45 final EventLoopGroup workerGroup) {
46 this(channelInitializer, bossGroup, workerGroup, GlobalEventExecutor.INSTANCE);
49 public NetconfServerFactoryImpl(final ServerChannelInitializer channelInitializer,
50 final EventLoopGroup parentGroup, final EventLoopGroup workerGroup, final EventExecutor executor) {
51 this.parentGroup = requireNonNull(parentGroup);
52 this.workerGroup = requireNonNull(workerGroup);
53 this.channelInitializer = channelInitializer;
54 transportChannelListener = new ChannelInitializerListener(channelInitializer, executor);
57 @NonNull protected ServerBootstrap createBootstrap() {
58 return NettyTransportSupport.newServerBootstrap().group(parentGroup, workerGroup);
62 public ListenableFuture<TCPServer> createTcpServer(final TcpServerGrouping params)
63 throws UnsupportedConfigurationException {
64 return TCPServer.listen(transportChannelListener, createBootstrap(), params);
68 public ListenableFuture<SSHServer> createSshServer(final TcpServerGrouping tcpParams,
69 final SshServerGrouping sshParams) throws UnsupportedConfigurationException {
70 return SSHServer.listen(EMPTY_LISTENER, createBootstrap(), tcpParams, sshParams);
74 public ListenableFuture<SSHServer> createSshServer(final TcpServerGrouping tcpParams,
75 final SshServerGrouping sshParams, final ServerFactoryManagerConfigurator configurator)
76 throws UnsupportedConfigurationException {
77 final var initializer = requireNonNull(channelInitializer);
79 return SSHServer.listen(EMPTY_LISTENER, createBootstrap(), tcpParams, sshParams, factoryManager -> {
80 if (configurator != null) {
81 configurator.configureServerFactoryManager(factoryManager);
83 if (factoryManager instanceof SshServer server) {
84 server.setSubsystemFactories(List.of(new NetconfSubsystemFactory(initializer)));
89 private record ChannelInitializerListener(
90 @Nullable ServerChannelInitializer channelInitializer,
91 @Nullable EventExecutor executor) implements TransportChannelListener {
93 public void onTransportChannelEstablished(final TransportChannel channel) {
94 LOG.debug("Transport channel {} established", channel);
95 if (channelInitializer != null && executor != null) {
96 channelInitializer.initialize(channel.channel(), new DefaultPromise<>(executor));
101 public void onTransportChannelFailed(final Throwable cause) {
102 LOG.error("Transport channel failed", cause);