Merge "Fixed for bug 1197"
[controller.git] / opendaylight / md-sal / sal-rest-connector / src / main / java / org / opendaylight / controller / sal / streams / websockets / WebSocketServer.java
1 package org.opendaylight.controller.sal.streams.websockets;
2
3 import com.google.common.base.Preconditions;
4 import io.netty.bootstrap.ServerBootstrap;
5 import io.netty.channel.Channel;
6 import io.netty.channel.EventLoopGroup;
7 import io.netty.channel.nio.NioEventLoopGroup;
8 import io.netty.channel.socket.nio.NioServerSocketChannel;
9 import org.opendaylight.controller.sal.streams.listeners.Notificator;
10 import org.slf4j.Logger;
11 import org.slf4j.LoggerFactory;
12
13 /**
14  * {@link WebSocketServer} is responsible to start and stop web socket server
15  */
16 public class WebSocketServer implements Runnable {
17
18     private static final Logger logger = LoggerFactory.getLogger(WebSocketServer.class);
19     public static final String WEBSOCKET_SERVER_CONFIG_PROPERTY = "restconf.websocket.port";
20     public static final int DEFAULT_PORT = 8181;
21     private EventLoopGroup bossGroup;
22     private EventLoopGroup workerGroup;
23     private static WebSocketServer singleton = null;
24     private int port = DEFAULT_PORT;
25
26     private WebSocketServer(int port) {
27         this.port = port;
28     }
29
30     /**
31      * Create instance of {@link WebSocketServer}
32      *
33      * @param port
34      *            TCP port used for this server
35      * @return instance of {@link WebSocketServer}
36      */
37     public static WebSocketServer createInstance(int port) {
38         if (singleton != null) {
39             throw new IllegalStateException("createInstance() has already been called");
40         }
41         if (port < 1024) {
42             throw new IllegalArgumentException("Privileged port (below 1024) is not allowed");
43         }
44         singleton = new WebSocketServer(port);
45         return singleton;
46     }
47
48     /**
49      * Return websocket TCP port
50      */
51     public int getPort() {
52         return port;
53     }
54
55     /**
56      * Get instance of {@link WebSocketServer} created by {@link #createInstance(int)}
57      *
58      * @return instance of {@link WebSocketServer}
59      */
60     public static WebSocketServer getInstance() {
61         Preconditions.checkNotNull(singleton, "createInstance() must be called prior to getInstance()");
62         return singleton;
63     }
64
65     /**
66      * Destroy this already created instance
67      */
68     public static void destroyInstance() {
69         if (singleton == null) {
70             throw new IllegalStateException("createInstance() must be called prior to destroyInstance()");
71         }
72         getInstance().stop();
73     }
74
75     @Override
76     public void run() {
77         bossGroup = new NioEventLoopGroup();
78         workerGroup = new NioEventLoopGroup();
79         try {
80             ServerBootstrap b = new ServerBootstrap();
81             b.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class)
82                     .childHandler(new WebSocketServerInitializer());
83
84             Channel ch = b.bind(port).sync().channel();
85             logger.info("Web socket server started at port {}.", port);
86
87             ch.closeFuture().sync();
88         } catch (InterruptedException e) {
89             // NOOP
90         } finally {
91             stop();
92         }
93     }
94
95     /**
96      * Stops the web socket server and removes all listeners.
97      */
98     private void stop() {
99         Notificator.removeAllListeners();
100         if (bossGroup != null) {
101             bossGroup.shutdownGracefully();
102         }
103         if (workerGroup != null) {
104             workerGroup.shutdownGracefully();
105         }
106     }
107
108 }