c0f958d2acb0ccd0fa0062e7a2fc8ce0a1e1bd69
[openflowjava.git] / openflow-protocol-impl / src / main / java / org / opendaylight / openflowjava / protocol / impl / core / UdpHandler.java
1 /*\r
2  * Copyright (c) 2014 Pantheon Technologies s.r.o. and others. All rights reserved.\r
3  *\r
4  * This program and the accompanying materials are made available under the\r
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
6  * and is available at http://www.eclipse.org/legal/epl-v10.html\r
7  */\r
8 \r
9 package org.opendaylight.openflowjava.protocol.impl.core;\r
10 \r
11 import io.netty.bootstrap.Bootstrap;\r
12 import io.netty.channel.ChannelFuture;\r
13 import io.netty.channel.ChannelOption;\r
14 import io.netty.channel.EventLoopGroup;\r
15 import io.netty.channel.nio.NioEventLoopGroup;\r
16 import io.netty.channel.socket.nio.NioDatagramChannel;\r
17 import io.netty.util.concurrent.GenericFutureListener;\r
18 \r
19 import java.net.InetAddress;\r
20 import java.net.InetSocketAddress;\r
21 \r
22 import org.opendaylight.openflowjava.protocol.api.connection.ThreadConfiguration;\r
23 import org.opendaylight.openflowjava.protocol.impl.connection.ServerFacade;\r
24 import org.slf4j.Logger;\r
25 import org.slf4j.LoggerFactory;\r
26 \r
27 import com.google.common.util.concurrent.ListenableFuture;\r
28 import com.google.common.util.concurrent.SettableFuture;\r
29 \r
30 /**\r
31  * Class implementing server over UDP for handling incoming connections.\r
32  * \r
33  * @author michal.polkorab\r
34  */\r
35 public final class UdpHandler implements ServerFacade {\r
36 \r
37     private static final Logger LOGGER = LoggerFactory\r
38             .getLogger(UdpHandler.class);\r
39     private int port;\r
40     private String address;\r
41     private EventLoopGroup group;\r
42     private final InetAddress startupAddress;\r
43     private final SettableFuture<Boolean> isOnlineFuture;\r
44     private UdpChannelInitializer channelInitializer;\r
45     private ThreadConfiguration threadConfig;\r
46 \r
47     /**\r
48      * Constructor of UdpHandler that listens on selected port.\r
49      *\r
50      * @param port listening port of UdpHandler server\r
51      */\r
52     public UdpHandler(final int port) {\r
53         this(null, port);\r
54     }\r
55 \r
56     /**\r
57      * Constructor of UdpHandler that listens on selected address and port.\r
58      * @param address listening address of UdpHandler server\r
59      * @param port listening port of UdpHandler server\r
60      */\r
61     public UdpHandler(final InetAddress address, final int port) {\r
62         this.port = port;\r
63         this.startupAddress = address;\r
64         isOnlineFuture = SettableFuture.create();\r
65     }\r
66 \r
67     @Override\r
68     public void run() {\r
69         if (threadConfig != null) {\r
70             group = new NioEventLoopGroup(threadConfig.getWorkerThreadCount());\r
71         } else {\r
72             group = new NioEventLoopGroup();\r
73         }\r
74         final ChannelFuture f;\r
75         try {\r
76             Bootstrap b = new Bootstrap();\r
77             b.group(group)\r
78              .channel(NioDatagramChannel.class)\r
79              .option(ChannelOption.SO_BROADCAST, false)\r
80              .handler(channelInitializer);\r
81 \r
82             if (startupAddress != null) {\r
83                 f = b.bind(startupAddress.getHostAddress(), port).sync();\r
84             } else {\r
85                 f = b.bind(port).sync();\r
86             }\r
87         } catch (InterruptedException e) {\r
88             LOGGER.error("Interrupted while binding port {}", port, e);\r
89             return;\r
90         }\r
91 \r
92         try {\r
93             InetSocketAddress isa = (InetSocketAddress) f.channel().localAddress();\r
94             this.address = isa.getHostString();\r
95 \r
96             // Update port, as it may have been specified as 0\r
97             this.port = isa.getPort();\r
98 \r
99             LOGGER.debug("Address from udpHandler: {}", address);\r
100             isOnlineFuture.set(true);\r
101             LOGGER.info("Switch listener started and ready to accept incoming udp connections on port: {}", port);\r
102             f.channel().closeFuture().sync();\r
103         } catch (InterruptedException e) {\r
104             LOGGER.error("Interrupted while waiting for port {} shutdown", port, e);\r
105         } finally {\r
106             shutdown();\r
107         }\r
108     }\r
109 \r
110     @Override\r
111     public ListenableFuture<Boolean> shutdown() {\r
112         final SettableFuture<Boolean> result = SettableFuture.create();\r
113         group.shutdownGracefully().addListener(new GenericFutureListener<io.netty.util.concurrent.Future<Object>>() {\r
114 \r
115             @Override\r
116             public void operationComplete(\r
117                     final io.netty.util.concurrent.Future<Object> downResult) throws Exception {\r
118                 result.set(downResult.isSuccess());\r
119                 if (downResult.cause() != null) {\r
120                     result.setException(downResult.cause());\r
121                 }\r
122             }\r
123 \r
124         });\r
125         return result;\r
126     }\r
127 \r
128     @Override\r
129     public ListenableFuture<Boolean> getIsOnlineFuture() {\r
130         return isOnlineFuture;\r
131     }\r
132 \r
133     /**\r
134      * @return the port\r
135      */\r
136     public int getPort() {\r
137         return port;\r
138     }\r
139 \r
140     /**\r
141      * @param channelInitializer\r
142      */\r
143     public void setChannelInitializer(UdpChannelInitializer channelInitializer) {\r
144         this.channelInitializer = channelInitializer;\r
145     }\r
146 \r
147     @Override\r
148     public void setThreadConfig(ThreadConfiguration threadConfig) {\r
149         this.threadConfig = threadConfig;\r
150     }\r
151 }