* 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 com.google.common.base.Preconditions;
+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;
* {@link WebSocketServer} is the singleton responsible for starting and stopping the
* web socket server.
*/
-public class WebSocketServer implements Runnable {
+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 int port) {
+ private WebSocketServer(final String address, final int port) {
+ this.address = address;
this.port = port;
}
* @param port TCP port used for this server
* @return instance of {@link WebSocketServer}
*/
- public static WebSocketServer createInstance(final int port) {
- Preconditions.checkState(instance == null, "createInstance() has already been called");
- Preconditions.checkArgument(port >= 1024, "Privileged port (below 1024) is not allowed");
+ 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(port);
+ instance = new WebSocketServer(requireNonNull(address, "Address cannot be null."), port);
+ LOG.info("Created WebSocketServer on {}:{}", address, port);
return instance;
}
* @return instance of {@link WebSocketServer}
*/
public static WebSocketServer getInstance() {
- Preconditions.checkNotNull(instance, "createInstance() must be called prior to getInstance()");
- return instance;
+ 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() {
- Preconditions.checkState(instance != null, "createInstance() must be called prior to 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();
serverBootstrap.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class)
.childHandler(new WebSocketServerInitializer());
- final Channel channel = serverBootstrap.bind(port).sync().channel();
- LOG.info("Web socket server started at port {}.", port);
+ 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.debug("Stopping the web socket server instance on port {}", port);
+ LOG.info("Stopping the web socket server instance on port {}", port);
Notificator.removeAllListeners();
if (bossGroup != null) {
bossGroup.shutdownGracefully();