Flatten callhome-provider
[netconf.git] / apps / callhome-provider / src / main / java / org / opendaylight / netconf / topology / callhome / CallHomeTlsServer.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.topology.callhome;
9
10 import static java.util.Objects.requireNonNull;
11
12 import io.netty.channel.ChannelOption;
13 import java.net.InetAddress;
14 import java.util.concurrent.ExecutionException;
15 import java.util.concurrent.TimeUnit;
16 import java.util.concurrent.TimeoutException;
17 import org.eclipse.jdt.annotation.NonNull;
18 import org.opendaylight.netconf.client.NetconfClientSessionNegotiatorFactory;
19 import org.opendaylight.netconf.transport.api.UnsupportedConfigurationException;
20 import org.opendaylight.netconf.transport.tcp.BootstrapFactory;
21 import org.opendaylight.netconf.transport.tls.TLSClient;
22 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IetfInetUtil;
23 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.PortNumber;
24 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.client.rev231228.netconf.client.listen.stack.grouping.transport.ssh.ssh.TcpServerParametersBuilder;
25 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.tcp.server.rev231228.TcpServerGrouping;
26 import org.opendaylight.yangtools.yang.common.Uint16;
27
28 public final class CallHomeTlsServer implements AutoCloseable {
29     private static final int DEFAULT_PORT = 4335;
30     private static final Integer DEFAULT_TIMEOUT_MILLIS = 5000;
31     private static final Integer DEFAULT_MAX_CONNECTIONS = 64;
32
33     private final CallHomeTlsSessionContextManager contextManager;
34     private final TLSClient client;
35
36     private CallHomeTlsServer(final TcpServerGrouping tcpServerParams,
37             final BootstrapFactory bootstrapFactory,
38             final Integer maxConnections, final Integer timeoutMillis,
39             final NetconfClientSessionNegotiatorFactory negotiationFactory,
40             final CallHomeTlsSessionContextManager contextManager,
41             final CallHomeTlsAuthProvider authProvider,
42             final CallHomeStatusRecorder statusRecorder) {
43         this.contextManager = requireNonNull(contextManager);
44         final var bootstrap = bootstrapFactory.newServerBootstrap()
45             .childOption(ChannelOption.SO_KEEPALIVE, true)
46             .childOption(ChannelOption.SO_BACKLOG, requireNonNull(maxConnections))
47             .childOption(ChannelOption.CONNECT_TIMEOUT_MILLIS, requireNonNull(timeoutMillis));
48         final var transportChannelListener = new CallHomeTransportChannelListener(requireNonNull(negotiationFactory),
49             contextManager, requireNonNull(statusRecorder));
50         try {
51             client = TLSClient.listen(transportChannelListener, bootstrap, tcpServerParams, authProvider)
52                 .get(timeoutMillis, TimeUnit.MILLISECONDS);
53         } catch (UnsupportedConfigurationException | InterruptedException | ExecutionException | TimeoutException e) {
54             throw new IllegalStateException("Could not start TLS Call-Home server", e);
55         }
56     }
57
58     @Override
59     public void close() throws Exception {
60         contextManager.close();
61         client.shutdown().get();
62     }
63
64     public static Builder builder() {
65         return new Builder();
66     }
67
68     public static final class Builder {
69
70         private InetAddress address;
71         private int port = DEFAULT_PORT;
72         private BootstrapFactory bootstrapFactory;
73         private NetconfClientSessionNegotiatorFactory negotiationFactory;
74         private Integer maxConnections;
75         private Integer timeoutMillis;
76         private CallHomeTlsAuthProvider authProvider;
77         private CallHomeTlsSessionContextManager contextManager;
78         private CallHomeStatusRecorder statusRecorder;
79
80         private Builder() {
81             // on purpose
82         }
83
84         public @NonNull CallHomeTlsServer build() {
85             return new CallHomeTlsServer(
86                 toServerParams(address, port),
87                 bootstrapFactory == null ? defaultBootstrapFactory() : bootstrapFactory,
88                 maxConnections == null ? DEFAULT_MAX_CONNECTIONS : maxConnections,
89                 timeoutMillis == null ? DEFAULT_TIMEOUT_MILLIS : timeoutMillis,
90                 negotiationFactory, contextManager, authProvider, statusRecorder);
91         }
92
93         public Builder withSessionContextManager(final CallHomeTlsSessionContextManager newContextManager) {
94             contextManager = newContextManager;
95             return this;
96         }
97
98         public Builder withAuthProvider(final CallHomeTlsAuthProvider newAuthProvider) {
99             authProvider = newAuthProvider;
100             return this;
101         }
102
103         public Builder withStatusRecorder(final CallHomeStatusRecorder newStatusRecorder) {
104             statusRecorder = newStatusRecorder;
105             return this;
106         }
107
108         public Builder withAddress(final InetAddress newAddress) {
109             address = newAddress;
110             return this;
111         }
112
113         public Builder withPort(final int newPort) {
114             port = newPort;
115             return this;
116         }
117
118         public Builder withMaxConnections(final int newMaxConnections) {
119             maxConnections = newMaxConnections;
120             return this;
121         }
122
123         public Builder withTimeout(final int newTimeoutMillis) {
124             timeoutMillis = newTimeoutMillis;
125             return this;
126         }
127
128         public Builder withBootstrapFactory(final BootstrapFactory newBootstrapFactory) {
129             bootstrapFactory = newBootstrapFactory;
130             return this;
131         }
132
133         public Builder withNegotiationFactory(final NetconfClientSessionNegotiatorFactory newNegotiationFactory) {
134             negotiationFactory = newNegotiationFactory;
135             return this;
136         }
137     }
138
139     private static TcpServerGrouping toServerParams(final InetAddress address, final int port) {
140         final var ipAddress = IetfInetUtil.ipAddressFor(
141             address == null ? InetAddress.getLoopbackAddress() : address);
142         final var portNumber = new PortNumber(Uint16.valueOf(port < 0 ? DEFAULT_PORT : port));
143         return new TcpServerParametersBuilder().setLocalAddress(ipAddress).setLocalPort(portNumber).build();
144     }
145
146     private static BootstrapFactory defaultBootstrapFactory() {
147         return new BootstrapFactory("tls-call-home-server", 0);
148     }
149 }