Allow SshClient to be customized via NetconfClientConfiguration
[netconf.git] / netconf / netconf-client / src / main / java / org / opendaylight / netconf / client / NetconfClientDispatcherImpl.java
1 /*
2  * Copyright (c) 2013 Cisco Systems, Inc. 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 io.netty.channel.EventLoopGroup;
11 import io.netty.util.Timer;
12 import io.netty.util.concurrent.Future;
13 import java.util.LinkedHashSet;
14 import java.util.List;
15 import java.util.Set;
16 import org.opendaylight.netconf.client.conf.NetconfClientConfiguration;
17 import org.opendaylight.netconf.client.conf.NetconfReconnectingClientConfiguration;
18 import org.opendaylight.netconf.nettyutil.AbstractNetconfDispatcher;
19 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Uri;
20 import org.slf4j.Logger;
21 import org.slf4j.LoggerFactory;
22
23 public class NetconfClientDispatcherImpl
24         extends AbstractNetconfDispatcher<NetconfClientSession, NetconfClientSessionListener>
25         implements NetconfClientDispatcher {
26
27     private static final Logger LOG = LoggerFactory.getLogger(NetconfClientDispatcherImpl.class);
28
29     private final Timer timer;
30
31     public NetconfClientDispatcherImpl(final EventLoopGroup bossGroup, final EventLoopGroup workerGroup,
32                                        final Timer timer) {
33         super(bossGroup, workerGroup);
34         this.timer = timer;
35     }
36
37     protected Timer getTimer() {
38         return timer;
39     }
40
41     @Override
42     public Future<NetconfClientSession> createClient(final NetconfClientConfiguration clientConfiguration) {
43         switch (clientConfiguration.getProtocol()) {
44             case TCP:
45                 return createTcpClient(clientConfiguration);
46             case SSH:
47                 return createSshClient(clientConfiguration);
48             case TLS:
49                 return createTlsClient(clientConfiguration);
50             default:
51                 throw new IllegalArgumentException("Unknown client protocol " + clientConfiguration.getProtocol());
52         }
53     }
54
55     @Override
56     public Future<Void> createReconnectingClient(final NetconfReconnectingClientConfiguration clientConfiguration) {
57         switch (clientConfiguration.getProtocol()) {
58             case TCP:
59                 return createReconnectingTcpClient(clientConfiguration);
60             case SSH:
61                 return createReconnectingSshClient(clientConfiguration);
62             case TLS:
63                 return createReconnectingTlsClient(clientConfiguration);
64             default:
65                 throw new IllegalArgumentException("Unknown client protocol " + clientConfiguration.getProtocol());
66         }
67     }
68
69     private Future<NetconfClientSession> createTcpClient(final NetconfClientConfiguration currentConfiguration) {
70         LOG.debug("Creating TCP client with configuration: {}", currentConfiguration);
71         return super.createClient(currentConfiguration.getAddress(), currentConfiguration.getReconnectStrategy(),
72             (ch, promise) -> new TcpClientChannelInitializer(getNegotiatorFactory(currentConfiguration),
73                         currentConfiguration.getSessionListener()).initialize(ch, promise));
74     }
75
76     private Future<Void> createReconnectingTcpClient(
77             final NetconfReconnectingClientConfiguration currentConfiguration) {
78         LOG.debug("Creating reconnecting TCP client with configuration: {}", currentConfiguration);
79         final TcpClientChannelInitializer init =
80                 new TcpClientChannelInitializer(getNegotiatorFactory(currentConfiguration),
81                 currentConfiguration.getSessionListener());
82
83         return super.createReconnectingClient(currentConfiguration.getAddress(), currentConfiguration
84                 .getConnectStrategyFactory(),
85                 currentConfiguration.getReconnectStrategy(), init::initialize);
86     }
87
88     private Future<NetconfClientSession> createSshClient(final NetconfClientConfiguration currentConfiguration) {
89         LOG.debug("Creating SSH client with configuration: {}", currentConfiguration);
90         return super.createClient(currentConfiguration.getAddress(), currentConfiguration.getReconnectStrategy(),
91             (ch, sessionPromise) -> new SshClientChannelInitializer(currentConfiguration.getAuthHandler(),
92                         getNegotiatorFactory(currentConfiguration), currentConfiguration.getSessionListener(),
93                         currentConfiguration.getSshClient()).initialize(ch, sessionPromise));
94     }
95
96     private Future<Void> createReconnectingSshClient(
97             final NetconfReconnectingClientConfiguration currentConfiguration) {
98         LOG.debug("Creating reconnecting SSH client with configuration: {}", currentConfiguration);
99         final SshClientChannelInitializer init = new SshClientChannelInitializer(currentConfiguration.getAuthHandler(),
100                 getNegotiatorFactory(currentConfiguration), currentConfiguration.getSessionListener(),
101                 currentConfiguration.getSshClient());
102
103         return super.createReconnectingClient(currentConfiguration.getAddress(), currentConfiguration
104                 .getConnectStrategyFactory(), currentConfiguration.getReconnectStrategy(),
105                 init::initialize);
106     }
107
108     private Future<NetconfClientSession> createTlsClient(final NetconfClientConfiguration currentConfiguration) {
109         LOG.debug("Creating TLS client with configuration: {}", currentConfiguration);
110         return super.createClient(currentConfiguration.getAddress(), currentConfiguration.getReconnectStrategy(),
111             (ch, sessionPromise) -> new TlsClientChannelInitializer(currentConfiguration.getSslHandlerFactory(),
112                     getNegotiatorFactory(currentConfiguration), currentConfiguration.getSessionListener())
113                     .initialize(ch, sessionPromise));
114     }
115
116     private Future<Void> createReconnectingTlsClient(
117             final NetconfReconnectingClientConfiguration currentConfiguration) {
118         LOG.debug("Creating reconnecting TLS client with configuration: {}", currentConfiguration);
119         final TlsClientChannelInitializer init = new TlsClientChannelInitializer(
120                 currentConfiguration.getSslHandlerFactory(), getNegotiatorFactory(currentConfiguration),
121                 currentConfiguration.getSessionListener());
122
123         return super.createReconnectingClient(currentConfiguration.getAddress(), currentConfiguration
124                 .getConnectStrategyFactory(), currentConfiguration.getReconnectStrategy(),
125                 init::initialize);
126     }
127
128     protected NetconfClientSessionNegotiatorFactory getNegotiatorFactory(final NetconfClientConfiguration cfg) {
129         final List<Uri> odlHelloCapabilities = cfg.getOdlHelloCapabilities();
130         if (odlHelloCapabilities == null || odlHelloCapabilities.isEmpty()) {
131             return new NetconfClientSessionNegotiatorFactory(timer, cfg.getAdditionalHeader(),
132                     cfg.getConnectionTimeoutMillis());
133         } else {
134             // LinkedHashSet since perhaps the device cares about order of hello message capabilities.
135             // This allows user control of the order while complying with the existing interface.
136             final Set<String> stringCapabilities = new LinkedHashSet<>();
137             for (final Uri uri : odlHelloCapabilities) {
138                 stringCapabilities.add(uri.getValue());
139             }
140             return new NetconfClientSessionNegotiatorFactory(timer, cfg.getAdditionalHeader(),
141                     cfg.getConnectionTimeoutMillis(), stringCapabilities);
142         }
143     }
144 }