940da73b68ae2b736964e52dfe68cdf8573d81a7
[netconf.git] / protocol / netconf-client / src / main / java / org / opendaylight / netconf / client / NetconfClientFactoryImpl.java
1 /*
2  * Copyright (c) 2023 PANTHEON.tech s.r.o. and others. All rights reserved.
3  *
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
7  */
8 package org.opendaylight.netconf.client;
9
10 import static java.util.Objects.requireNonNull;
11
12 import com.google.common.collect.ImmutableSet;
13 import com.google.common.util.concurrent.ListenableFuture;
14 import javax.annotation.PreDestroy;
15 import javax.inject.Inject;
16 import javax.inject.Singleton;
17 import org.eclipse.jdt.annotation.NonNull;
18 import org.opendaylight.netconf.api.TransportConstants;
19 import org.opendaylight.netconf.client.conf.NetconfClientConfiguration;
20 import org.opendaylight.netconf.common.NetconfTimer;
21 import org.opendaylight.netconf.transport.api.UnsupportedConfigurationException;
22 import org.opendaylight.netconf.transport.ssh.SSHTransportStackFactory;
23 import org.opendaylight.netconf.transport.tcp.TCPClient;
24 import org.opendaylight.netconf.transport.tls.FixedSslHandlerFactory;
25 import org.opendaylight.netconf.transport.tls.TLSClient;
26 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Uri;
27 import org.osgi.service.component.annotations.Activate;
28 import org.osgi.service.component.annotations.Component;
29 import org.osgi.service.component.annotations.Deactivate;
30 import org.osgi.service.component.annotations.Reference;
31 import org.slf4j.Logger;
32 import org.slf4j.LoggerFactory;
33
34 @Singleton
35 @Component(service = NetconfClientFactory.class)
36 public final class NetconfClientFactoryImpl implements NetconfClientFactory {
37     private static final Logger LOG = LoggerFactory.getLogger(NetconfClientFactoryImpl.class);
38
39     private final SSHTransportStackFactory factory;
40     private final NetconfTimer timer;
41
42     public NetconfClientFactoryImpl(final NetconfTimer timer, final SSHTransportStackFactory factory) {
43         this.timer = requireNonNull(timer);
44         this.factory = requireNonNull(factory);
45     }
46
47     @Inject
48     @Activate
49     public NetconfClientFactoryImpl(@Reference final NetconfTimer timer) {
50         // FIXME: make factory component configurable for OSGi
51         this(timer, new SSHTransportStackFactory("odl-netconf-client", 0));
52     }
53
54     @PreDestroy
55     @Deactivate
56     @Override
57     public void close() {
58         factory.close();
59     }
60
61     @Override
62     public ListenableFuture<NetconfClientSession> createClient(final NetconfClientConfiguration configuration)
63             throws UnsupportedConfigurationException {
64         final var sessionListener = configuration.getSessionListener();
65         final var transportListener = new ClientTransportChannelListener(new ClientChannelInitializer(
66             createNegotiatorFactory(configuration), () -> sessionListener));
67
68         final var stackFuture = switch (configuration.getProtocol()) {
69             case SSH -> factory.connectClient(TransportConstants.SSH_SUBSYSTEM, transportListener,
70                 configuration.getTcpParameters(), configuration.getSshParameters(), configuration.getSshConfigurator());
71             case TCP -> TCPClient.connect(transportListener, factory.newBootstrap(), configuration.getTcpParameters());
72             case TLS -> {
73                 var handlerFactory = configuration.getSslHandlerFactory();
74                 if (handlerFactory == null) {
75                     handlerFactory = new FixedSslHandlerFactory(configuration.getTlsParameters());
76                 }
77                 yield TLSClient.connect(transportListener, factory.newBootstrap(), configuration.getTcpParameters(),
78                     handlerFactory);
79             }
80         };
81         LOG.trace("Future stack is {}", stackFuture);
82
83         return transportListener.sessionFuture();
84     }
85
86     private @NonNull NetconfClientSessionNegotiatorFactory createNegotiatorFactory(
87             final NetconfClientConfiguration configuration) {
88         final var capabilities = configuration.getOdlHelloCapabilities();
89         if (capabilities == null || capabilities.isEmpty()) {
90             return new NetconfClientSessionNegotiatorFactory(timer, configuration.getAdditionalHeader(),
91                 configuration.getConnectionTimeoutMillis(), configuration.getMaximumIncomingChunkSize());
92         }
93         final var stringCapabilities = capabilities.stream().map(Uri::getValue)
94             .collect(ImmutableSet.toImmutableSet());
95         return new NetconfClientSessionNegotiatorFactory(timer, configuration.getAdditionalHeader(),
96             configuration.getConnectionTimeoutMillis(), stringCapabilities);
97     }
98 }