2ebeec76fca26e9b5aabb782f224af156f54cb05
[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.slf4j.Logger;\r
24 import org.slf4j.LoggerFactory;\r
25 \r
26 import com.google.common.util.concurrent.ListenableFuture;\r
27 import com.google.common.util.concurrent.SettableFuture;\r
28 \r
29 /**\r
30  * Class implementing server over UDP for handling incoming connections.\r
31  * \r
32  * @author michal.polkorab\r
33  */\r
34 public final class UdpHandler implements ServerFacade {\r
35 \r
36     private static final Logger LOGGER = LoggerFactory\r
37             .getLogger(UdpHandler.class);\r
38     private int port;\r
39     private EventLoopGroup group;\r
40     private final InetAddress startupAddress;\r
41     private final SettableFuture<Boolean> isOnlineFuture;\r
42     private UdpChannelInitializer channelInitializer;\r
43     private ThreadConfiguration threadConfig;\r
44 \r
45     /**\r
46      * Constructor of UdpHandler that listens on selected port.\r
47      *\r
48      * @param port listening port of UdpHandler server\r
49      */\r
50     public UdpHandler(final int port) {\r
51         this(null, port);\r
52     }\r
53 \r
54     /**\r
55      * Constructor of UdpHandler that listens on selected address and port.\r
56      * @param address listening address of UdpHandler server\r
57      * @param port listening port of UdpHandler server\r
58      */\r
59     public UdpHandler(final InetAddress address, final int port) {\r
60         this.port = port;\r
61         this.startupAddress = address;\r
62         isOnlineFuture = SettableFuture.create();\r
63     }\r
64 \r
65     @Override\r
66     public void run() {\r
67         if (threadConfig != null) {\r
68             group = new NioEventLoopGroup(threadConfig.getWorkerThreadCount());\r
69         } else {\r
70             group = new NioEventLoopGroup();\r
71         }\r
72         final ChannelFuture f;\r
73         try {\r
74             Bootstrap b = new Bootstrap();\r
75             b.group(group)\r
76              .channel(NioDatagramChannel.class)\r
77              .option(ChannelOption.SO_BROADCAST, false)\r
78              .handler(channelInitializer);\r
79 \r
80             if (startupAddress != null) {\r
81                 f = b.bind(startupAddress.getHostAddress(), port).sync();\r
82             } else {\r
83                 f = b.bind(port).sync();\r
84             }\r
85         } catch (InterruptedException e) {\r
86             LOGGER.error("Interrupted while binding port {}", port, e);\r
87             return;\r
88         }\r
89 \r
90         try {\r
91             InetSocketAddress isa = (InetSocketAddress) f.channel().localAddress();\r
92             String address = isa.getHostString();\r
93 \r
94             // Update port, as it may have been specified as 0\r
95             this.port = isa.getPort();\r
96 \r
97             LOGGER.debug("Address from udpHandler: {}", address);\r
98             isOnlineFuture.set(true);\r
99             LOGGER.info("Switch listener started and ready to accept incoming udp connections on port: {}", port);\r
100             f.channel().closeFuture().sync();\r
101         } catch (InterruptedException e) {\r
102             LOGGER.error("Interrupted while waiting for port {} shutdown", port, e);\r
103         } finally {\r
104             shutdown();\r
105         }\r
106     }\r
107 \r
108     @Override\r
109     public ListenableFuture<Boolean> shutdown() {\r
110         final SettableFuture<Boolean> result = SettableFuture.create();\r
111         group.shutdownGracefully().addListener(new GenericFutureListener<io.netty.util.concurrent.Future<Object>>() {\r
112 \r
113             @Override\r
114             public void operationComplete(\r
115                     final io.netty.util.concurrent.Future<Object> downResult) throws Exception {\r
116                 result.set(downResult.isSuccess());\r
117                 if (downResult.cause() != null) {\r
118                     result.setException(downResult.cause());\r
119                 }\r
120             }\r
121 \r
122         });\r
123         return result;\r
124     }\r
125 \r
126     @Override\r
127     public ListenableFuture<Boolean> getIsOnlineFuture() {\r
128         return isOnlineFuture;\r
129     }\r
130 \r
131     /**\r
132      * @return the port\r
133      */\r
134     public int getPort() {\r
135         return port;\r
136     }\r
137 \r
138     /**\r
139      * @param channelInitializer\r
140      */\r
141     public void setChannelInitializer(UdpChannelInitializer channelInitializer) {\r
142         this.channelInitializer = channelInitializer;\r
143     }\r
144 \r
145     @Override\r
146     public void setThreadConfig(ThreadConfiguration threadConfig) {\r
147         this.threadConfig = threadConfig;\r
148     }\r
149 }