2 * Copyright (c) 2022 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.transport.tcp;
10 import io.netty.bootstrap.Bootstrap;
11 import io.netty.bootstrap.ServerBootstrap;
12 import io.netty.channel.ChannelOption;
13 import io.netty.channel.EventLoopGroup;
14 import io.netty.channel.nio.NioEventLoopGroup;
15 import io.netty.channel.socket.SocketChannelConfig;
16 import io.netty.channel.socket.nio.NioChannelOption;
17 import io.netty.channel.socket.nio.NioServerSocketChannel;
18 import io.netty.channel.socket.nio.NioSocketChannel;
20 import java.util.concurrent.ThreadFactory;
21 import jdk.net.ExtendedSocketOptions;
22 import org.eclipse.jdt.annotation.NonNullByDefault;
23 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.tcp.common.rev231228.tcp.common.grouping.Keepalives;
24 import org.slf4j.LoggerFactory;
27 final class NioNettyImpl extends AbstractNettyImpl {
28 // FIXME: all of this is a workaround for https://issues.apache.org/jira/browse/KARAF-7690
29 private abstract static class AbstractSupport {
31 abstract boolean configureKeepalives(SocketChannelConfig config);
33 abstract void configureKeepalives(ServerBootstrap bootstrap, Keepalives keepalives);
35 abstract void configureKeepalives(Bootstrap bootstrap, Keepalives keepalives);
38 private static final class Supported extends AbstractSupport {
39 private static final ChannelOption<Integer> TCP_KEEPIDLE =
40 NioChannelOption.of(ExtendedSocketOptions.TCP_KEEPIDLE);
41 private static final ChannelOption<Integer> TCP_KEEPCNT =
42 NioChannelOption.of(ExtendedSocketOptions.TCP_KEEPCOUNT);
43 private static final ChannelOption<Integer> TCP_KEEPINTVL =
44 NioChannelOption.of(ExtendedSocketOptions.TCP_KEEPINTERVAL);
47 boolean configureKeepalives(final SocketChannelConfig config) {
48 return config.setOptions(Map.of(
49 ChannelOption.SO_KEEPALIVE, Boolean.TRUE, TCP_KEEPIDLE, 7200, TCP_KEEPCNT, 3, TCP_KEEPINTVL, 5));
53 void configureKeepalives(final ServerBootstrap bootstrap, final Keepalives keepalives) {
55 .childOption(TCP_KEEPIDLE, keepalives.requireIdleTime().toJava())
56 .childOption(TCP_KEEPCNT, keepalives.requireMaxProbes().toJava())
57 .childOption(TCP_KEEPINTVL, keepalives.requireProbeInterval().toJava());
61 void configureKeepalives(final Bootstrap bootstrap, final Keepalives keepalives) {
63 .option(TCP_KEEPIDLE, keepalives.requireIdleTime().toJava())
64 .option(TCP_KEEPCNT, keepalives.requireMaxProbes().toJava())
65 .option(TCP_KEEPINTVL, keepalives.requireProbeInterval().toJava());
69 private static final class Unsupported extends AbstractSupport {
71 boolean configureKeepalives(final SocketChannelConfig config) {
76 void configureKeepalives(final ServerBootstrap bootstrap, final Keepalives keepalives) {
81 void configureKeepalives(final Bootstrap bootstrap, final Keepalives keepalives) {
86 private static final AbstractSupport SUPPORT;
89 AbstractSupport support;
92 support = new Supported();
93 } catch (NoClassDefFoundError e) {
94 LoggerFactory.getLogger(NioNettyImpl.class).warn("Disabling keepalive support", e);
95 support = new Unsupported();
101 static final NioNettyImpl INSTANCE;
104 final var grp = new NioEventLoopGroup();
107 final var ch = new NioSocketChannel();
108 grp.register(ch).sync();
110 final boolean supportsKeepalives;
112 supportsKeepalives = SUPPORT.configureKeepalives(ch.config());
116 INSTANCE = new NioNettyImpl(supportsKeepalives);
118 grp.shutdownGracefully().sync();
120 } catch (InterruptedException e) {
121 Thread.currentThread().interrupt();
122 throw new ExceptionInInitializerError(e);
126 private final boolean supportsKeepalives;
128 private NioNettyImpl(final boolean supportsKeepalives) {
129 this.supportsKeepalives = supportsKeepalives;
133 Class<NioSocketChannel> channelClass() {
134 return NioSocketChannel.class;
138 Class<NioServerSocketChannel> serverChannelClass() {
139 return NioServerSocketChannel.class;
143 EventLoopGroup newEventLoopGroup(final int numThreads, final ThreadFactory threadFactory) {
144 return new NioEventLoopGroup(numThreads, threadFactory);
148 boolean supportsKeepalives() {
149 return supportsKeepalives;
153 void configureKeepalives(final Bootstrap bootstrap, final Keepalives keepalives) {
154 SUPPORT.configureKeepalives(bootstrap.option(ChannelOption.SO_KEEPALIVE, Boolean.TRUE), keepalives);
158 void configureKeepalives(final ServerBootstrap bootstrap, final Keepalives keepalives) {
159 SUPPORT.configureKeepalives(bootstrap.childOption(ChannelOption.SO_KEEPALIVE, Boolean.TRUE), keepalives);
163 public String toString() {