Fix TCPServer javadoc
[netconf.git] / transport / transport-tcp / src / main / java / org / opendaylight / netconf / transport / tcp / TCPServer.java
1 /*
2  * Copyright (c) 2022 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.transport.tcp;
9
10 import static com.google.common.base.Verify.verifyNotNull;
11 import static java.util.Objects.requireNonNull;
12
13 import com.google.common.annotations.VisibleForTesting;
14 import com.google.common.util.concurrent.ListenableFuture;
15 import com.google.common.util.concurrent.SettableFuture;
16 import io.netty.bootstrap.ServerBootstrap;
17 import io.netty.channel.Channel;
18 import io.netty.channel.ChannelFutureListener;
19 import io.netty.channel.ChannelHandler.Sharable;
20 import io.netty.channel.ChannelInitializer;
21 import org.eclipse.jdt.annotation.NonNull;
22 import org.opendaylight.netconf.transport.api.TransportChannelListener;
23 import org.opendaylight.netconf.transport.api.UnsupportedConfigurationException;
24 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.tcp.server.rev240208.TcpServerGrouping;
25 import org.opendaylight.yangtools.yang.common.Empty;
26
27 /**
28  * A {@link TCPTransportStack} acting as a TCP server.
29  */
30 public final class TCPServer extends TCPTransportStack {
31     @Sharable
32     private static final class ListenChannelInitializer extends ChannelInitializer<Channel> {
33         private final TCPServer stack;
34
35         ListenChannelInitializer(final TCPServer stack) {
36             this.stack = requireNonNull(stack);
37         }
38
39         @Override
40         protected void initChannel(final Channel ch) {
41             verifyNotNull(stack, "Stack not initialized while handling channel %s", ch)
42                 .addTransportChannel(new TCPTransportChannel(ch));
43         }
44     }
45
46     private volatile Channel listenChannel;
47
48     private TCPServer(final TransportChannelListener listener) {
49         super(listener);
50     }
51
52     /**
53      * Attempt to establish a {@link TCPServer} which listens on a remote address.
54      *
55      * @param listener {@link TransportChannelListener} to notify when the session is established
56      * @param bootstrap {@link ServerBootstrap} to use for the underlying Netty server channel
57      * @param listenParams Listening parameters
58      * @return A future
59      * @throws UnsupportedConfigurationException when {@code listenParams} contains an unsupported options
60      * @throws NullPointerException if any argument is {@code null}
61      */
62     public static @NonNull ListenableFuture<TCPServer> listen(final TransportChannelListener listener,
63             final ServerBootstrap bootstrap, final TcpServerGrouping listenParams)
64                 throws UnsupportedConfigurationException {
65         NettyTransportSupport.configureKeepalives(bootstrap, listenParams.getKeepalives());
66
67         final var ret = SettableFuture.<TCPServer>create();
68         final var stack = new TCPServer(listener);
69         final var initializer = new ListenChannelInitializer(stack);
70         bootstrap
71             .childHandler(initializer)
72             .bind(socketAddressOf(listenParams.requireLocalAddress(), listenParams.requireLocalPort()))
73             .addListener((ChannelFutureListener) future -> {
74                 final var cause = future.cause();
75                 if (cause == null) {
76                     stack.setListenChannel(future.channel());
77                     ret.set(stack);
78                 } else {
79                     ret.setException(cause);
80                 }
81             });
82         return ret;
83     }
84
85     @Override
86     protected ListenableFuture<Empty> startShutdown() {
87         return toListenableFuture(listenChannel().close());
88     }
89
90     @VisibleForTesting
91     @NonNull Channel listenChannel() {
92         return verifyNotNull(listenChannel, "Channel not initialized");
93     }
94
95     private void setListenChannel(final Channel listenChannel) {
96         this.listenChannel = requireNonNull(listenChannel);
97     }
98 }