Use a random port in test server
[yangtools.git] / websocket / websocket-client / src / test / java / org / opendaylight / yangtools / websocket / server / WebSocketServer.java
1 /*
2  * Copyright 2012 The Netty Project
3  *
4  * The Netty Project licenses this file to you under the Apache License,
5  * version 2.0 (the "License"); you may not use this file except in compliance
6  * with the License. You may obtain a copy of the License at:
7  *
8  *   http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13  * License for the specific language governing permissions and limitations
14  * under the License.
15  */
16 package org.opendaylight.yangtools.websocket.server;
17
18 import io.netty.bootstrap.ServerBootstrap;
19 import io.netty.channel.Channel;
20 import io.netty.channel.EventLoopGroup;
21 import io.netty.channel.nio.NioEventLoopGroup;
22 import io.netty.channel.socket.nio.NioServerSocketChannel;
23
24 import org.slf4j.Logger;
25 import org.slf4j.LoggerFactory;
26
27 import java.net.SocketAddress;
28 import java.net.InetSocketAddress;
29
30 import java.util.concurrent.Future;
31 import java.util.concurrent.TimeUnit;
32 import java.util.concurrent.ExecutionException;
33 import java.util.concurrent.TimeoutException;
34
35 import com.google.common.util.concurrent.SettableFuture;
36
37 /**
38  * A HTTP server which serves Web Socket requests at:
39  *
40  * http://localhost:8080/websocket
41  *
42  * Open your browser at http://localhost:8080/, then the demo page will be loaded and a Web Socket connection will be
43  * made automatically.
44  *
45  * This server illustrates support for the different web socket specification versions and will work with:
46  *
47  * <ul>
48  * <li>Safari 5+ (draft-ietf-hybi-thewebsocketprotocol-00)
49  * <li>Chrome 6-13 (draft-ietf-hybi-thewebsocketprotocol-00)
50  * <li>Chrome 14+ (draft-ietf-hybi-thewebsocketprotocol-10)
51  * <li>Chrome 16+ (RFC 6455 aka draft-ietf-hybi-thewebsocketprotocol-17)
52  * <li>Firefox 7+ (draft-ietf-hybi-thewebsocketprotocol-10)
53  * <li>Firefox 11+ (RFC 6455 aka draft-ietf-hybi-thewebsocketprotocol-17)
54  * </ul>
55  */
56 public class WebSocketServer implements Runnable {
57
58     /**
59      * Utilized to get the port on which the server listens. This is a future as
60      * the port is selected dynamically from available ports, thus until the
61      * server is started the value will not be established.
62      */
63     private final SettableFuture<Integer> port;
64
65     /**
66      * Maintains the port number with which the class was initialized.
67      */
68     private final int inPort;
69     private final ServerBootstrap bootstrap = new ServerBootstrap();
70     private final EventLoopGroup bossGroup = new NioEventLoopGroup();
71     private final EventLoopGroup workerGroup = new NioEventLoopGroup();
72     private static final Logger logger = LoggerFactory.getLogger(WebSocketServer.class.toString());
73
74
75     public WebSocketServer(int inPort) {
76         this.inPort = inPort;
77         port = SettableFuture.<Integer>create();
78     }
79
80     public void run(){
81         try {
82             startServer();
83         } catch (Exception e) {
84             logger.info("Exception occured while starting webSocket server {}",e);
85         }
86     }
87
88     public Future<Integer> getPort() {
89         return port;
90     }
91
92     public void startServer() throws Exception {
93         try {
94             bootstrap.group(bossGroup, workerGroup)
95              .channel(NioServerSocketChannel.class)
96              .childHandler(new WebSocketServerInitializer());
97
98             Channel ch = bootstrap.bind(inPort).sync().channel();
99             SocketAddress localSocket = ch.localAddress();
100             try {
101                 port.set(((InetSocketAddress) localSocket).getPort());
102             } catch (ClassCastException cce) {
103                 throw new ExecutionException("Unknown socket address type", cce);
104             }
105             logger.info("Web socket server started at port " + port.get() + '.');
106             logger.info("Open your browser and navigate to http://localhost:" + port.get() + '/');
107
108             try {
109                 ch.closeFuture().sync();
110             } catch (InterruptedException ie) {
111                 // No op, sometimes the server is shutdown hard
112             }
113         } finally {
114             bossGroup.shutdownGracefully();
115             workerGroup.shutdownGracefully();
116         }
117     }
118 }