diff options
author | Dan Timoney <dtimoney@att.com> | 2023-01-05 09:31:25 -0500 |
---|---|---|
committer | Dan Timoney <dtimoney@att.com> | 2023-01-05 09:31:25 -0500 |
commit | d4d6fbd430eb502cce6cb01a667ec799d487a510 (patch) | |
tree | aea94837cd313f27f68e625d2b8277960fdf7af6 /netconf/restconf/restconf-nb-bierman02/src/main/java/org/opendaylight/netconf/sal/streams/websockets/WebSocketServer.java | |
parent | d0508aaeb7af3f29095d1d0ef7dbf69af18f0d99 (diff) |
Seed code for biermann restconf
Seed initial code from OpenDaylight netconf project for
Biermann draft version of restconf API
Issue-ID: CCSDK-3783
Signed-off-by: Dan Timoney <dtimoney@att.com>
Change-Id: I8a1ad2050ee7addbb480f01bd448922803bff31f
Diffstat (limited to 'netconf/restconf/restconf-nb-bierman02/src/main/java/org/opendaylight/netconf/sal/streams/websockets/WebSocketServer.java')
-rw-r--r-- | netconf/restconf/restconf-nb-bierman02/src/main/java/org/opendaylight/netconf/sal/streams/websockets/WebSocketServer.java | 152 |
1 files changed, 152 insertions, 0 deletions
diff --git a/netconf/restconf/restconf-nb-bierman02/src/main/java/org/opendaylight/netconf/sal/streams/websockets/WebSocketServer.java b/netconf/restconf/restconf-nb-bierman02/src/main/java/org/opendaylight/netconf/sal/streams/websockets/WebSocketServer.java new file mode 100644 index 0000000..a295c54 --- /dev/null +++ b/netconf/restconf/restconf-nb-bierman02/src/main/java/org/opendaylight/netconf/sal/streams/websockets/WebSocketServer.java @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2014, 2015 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.netconf.sal.streams.websockets; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkState; +import static java.util.Objects.requireNonNull; + +import io.netty.bootstrap.ServerBootstrap; +import io.netty.channel.Channel; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.nio.NioServerSocketChannel; +import org.opendaylight.netconf.sal.streams.listeners.Notificator; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * {@link WebSocketServer} is the singleton responsible for starting and stopping the + * web socket server. + */ +public final class WebSocketServer implements Runnable { + + private static final Logger LOG = LoggerFactory.getLogger(WebSocketServer.class); + + private static final String DEFAULT_ADDRESS = "0.0.0.0"; + + private static WebSocketServer instance = null; + + private final String address; + private final int port; + + private EventLoopGroup bossGroup; + private EventLoopGroup workerGroup; + + + private WebSocketServer(final String address, final int port) { + this.address = address; + this.port = port; + } + + /** + * Create singleton instance of {@link WebSocketServer}. + * + * @param port TCP port used for this server + * @return instance of {@link WebSocketServer} + */ + private static WebSocketServer createInstance(final int port) { + instance = createInstance(DEFAULT_ADDRESS, port); + return instance; + } + + public static WebSocketServer createInstance(final String address, final int port) { + checkState(instance == null, "createInstance() has already been called"); + checkArgument(port >= 1024, "Privileged port (below 1024) is not allowed"); + + instance = new WebSocketServer(requireNonNull(address, "Address cannot be null."), port); + LOG.info("Created WebSocketServer on {}:{}", address, port); + return instance; + } + + /** + * Get the websocket of TCP port. + * + * @return websocket TCP port + */ + public int getPort() { + return port; + } + + /** + * Get instance of {@link WebSocketServer} created by {@link #createInstance(int)}. + * + * @return instance of {@link WebSocketServer} + */ + public static WebSocketServer getInstance() { + return requireNonNull(instance, "createInstance() must be called prior to getInstance()"); + } + + /** + * Get instance of {@link WebSocketServer} created by {@link #createInstance(int)}. + * If an instance doesnt exist create one with the provided fallback port. + * + * @return instance of {@link WebSocketServer} + */ + public static WebSocketServer getInstance(final int fallbackPort) { + if (instance != null) { + return instance; + } + + LOG.warn("No instance for WebSocketServer found, creating one with a fallback port: {}", fallbackPort); + return createInstance(fallbackPort); + } + + /** + * Destroy the existing instance. + */ + public static void destroyInstance() { + checkState(instance != null, "createInstance() must be called prior to destroyInstance()"); + + instance.stop(); + instance = null; + LOG.info("Destroyed WebSocketServer."); + } + + @Override + @SuppressWarnings("checkstyle:IllegalCatch") + public void run() { + bossGroup = new NioEventLoopGroup(); + workerGroup = new NioEventLoopGroup(); + try { + final ServerBootstrap serverBootstrap = new ServerBootstrap(); + serverBootstrap.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class) + .childHandler(new WebSocketServerInitializer()); + + final Channel channel = serverBootstrap.bind(address, port).sync().channel(); + LOG.info("Web socket server started at address {}, port {}.", address, port); + + channel.closeFuture().sync(); + } catch (final InterruptedException e) { + LOG.error("Web socket server encountered an error during startup attempt on port {}", port, e); + } catch (Throwable throwable) { + // sync() re-throws exceptions declared as Throwable, so the compiler doesn't see them + LOG.error("Error while binding to address {}, port {}", address, port, throwable); + throw throwable; + } finally { + stop(); + } + } + + /** + * Stops the web socket server and removes all listeners. + */ + private void stop() { + LOG.info("Stopping the web socket server instance on port {}", port); + Notificator.removeAllListeners(); + if (bossGroup != null) { + bossGroup.shutdownGracefully(); + bossGroup = null; + } + if (workerGroup != null) { + workerGroup.shutdownGracefully(); + workerGroup = null; + } + } + +} |