2 * Copyright (c) 2013 Pantheon Technologies s.r.o. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
9 package org.opendaylight.openflowjava.protocol.impl.core;
11 import io.netty.bootstrap.ServerBootstrap;
12 import io.netty.channel.ChannelFuture;
13 import io.netty.channel.ChannelOption;
14 import io.netty.channel.nio.NioEventLoopGroup;
15 import io.netty.channel.socket.nio.NioServerSocketChannel;
16 import io.netty.handler.logging.LogLevel;
17 import io.netty.handler.logging.LoggingHandler;
18 import io.netty.util.concurrent.GenericFutureListener;
20 import java.net.InetAddress;
21 import java.net.InetSocketAddress;
23 import org.opendaylight.openflowjava.protocol.api.connection.SwitchConnectionHandler;
24 import org.opendaylight.openflowjava.protocol.impl.connection.ServerFacade;
25 import org.opendaylight.openflowjava.protocol.impl.serialization.SerializationFactory;
26 import org.opendaylight.openflowjava.protocol.impl.deserialization.DeserializationFactory;
27 import org.slf4j.Logger;
28 import org.slf4j.LoggerFactory;
30 import com.google.common.util.concurrent.ListenableFuture;
31 import com.google.common.util.concurrent.SettableFuture;
34 * Class implementing server over TCP for handling incoming connections.
36 * @author michal.polkorab
38 public class TcpHandler implements ServerFacade {
41 private String address;
42 private InetAddress startupAddress;
43 private NioEventLoopGroup workerGroup;
44 private NioEventLoopGroup bossGroup;
45 private static final Logger LOGGER = LoggerFactory.getLogger(TcpHandler.class);
46 private SettableFuture<Boolean> isOnlineFuture;
49 private PublishingChannelInitializer channelInitializer;
52 * Enum used for storing names of used components (in pipeline).
54 public static enum COMPONENT_NAMES {
57 * Detects switch idle state
61 * Detects TLS connections
65 * Component for handling TLS frames
69 * Decodes incoming messages into message frames
73 * Detects version of incoming OpenFlow Protocol message
77 * Transforms OpenFlow Protocol byte messages into POJOs
81 * Transforms POJOs into OpenFlow Protocol byte messages
85 * Delegates translated POJOs into MessageConsumer
87 DELEGATING_INBOUND_HANDLER,
92 * Constructor of TCPHandler that listens on selected port.
94 * @param port listening port of TCPHandler server
96 public TcpHandler(int port) {
101 * Constructor of TCPHandler that listens on selected address and port.
102 * @param address listening address of TCPHandler server
103 * @param port listening port of TCPHandler server
105 public TcpHandler(InetAddress address, int port) {
107 this.startupAddress = address;
108 channelInitializer = new PublishingChannelInitializer();
109 isOnlineFuture = SettableFuture.create();
113 * Starts server on selected port.
117 bossGroup = new NioEventLoopGroup();
118 workerGroup = new NioEventLoopGroup();
120 ServerBootstrap b = new ServerBootstrap();
121 b.group(bossGroup, workerGroup)
122 .channel(NioServerSocketChannel.class)
123 .handler(new LoggingHandler(LogLevel.DEBUG))
124 .childHandler(channelInitializer)
125 .option(ChannelOption.SO_BACKLOG, 128)
126 .option(ChannelOption.SO_REUSEADDR, true)
127 .childOption(ChannelOption.SO_KEEPALIVE, true);
130 if (startupAddress != null) {
131 f = b.bind(startupAddress.getHostAddress(), port).sync();
133 f = b.bind(port).sync();
136 InetSocketAddress isa = (InetSocketAddress) f.channel().localAddress();
137 address = isa.getHostString();
138 LOGGER.debug("address from tcphandler: " + address);
139 port = isa.getPort();
140 isOnlineFuture.set(true);
141 LOGGER.info("Switch listener started and ready to accept incoming connections on port: " + port);
142 f.channel().closeFuture().sync();
143 } catch (InterruptedException ex) {
144 LOGGER.error(ex.getMessage(), ex);
151 * Shuts down {@link TcpHandler}}
154 public ListenableFuture<Boolean> shutdown() {
155 final SettableFuture<Boolean> result = SettableFuture.create();
156 workerGroup.shutdownGracefully();
157 // boss will shutdown as soon, as worker is down
158 bossGroup.shutdownGracefully().addListener(new GenericFutureListener<io.netty.util.concurrent.Future<Object>>() {
161 public void operationComplete(
162 io.netty.util.concurrent.Future<Object> downResult) throws Exception {
163 result.set(downResult.isSuccess());
164 if (downResult.cause() != null) {
165 result.setException(downResult.cause());
175 * @return number of connected clients / channels
177 public int getNumberOfConnections() {
178 return channelInitializer.size();
182 * @return channelInitializer providing channels
184 public PublishingChannelInitializer getChannelInitializer() {
185 return channelInitializer;
189 public ListenableFuture<Boolean> getIsOnlineFuture() {
190 return isOnlineFuture;
196 public int getPort() {
201 * @return the address
203 public String getAddress() {
208 * @param switchConnectionHandler
210 public void setSwitchConnectionHandler(
211 SwitchConnectionHandler switchConnectionHandler) {
212 channelInitializer.setSwitchConnectionHandler(switchConnectionHandler);
216 * @param switchIdleTimeout in milliseconds
218 public void setSwitchIdleTimeout(long switchIdleTimeout) {
219 channelInitializer.setSwitchIdleTimeout(switchIdleTimeout);
223 * @param tlsSupported
225 public void setEncryption(boolean tlsSupported) {
226 channelInitializer.setEncryption(tlsSupported);
230 * @param sf serialization factory
232 public void setSerializationFactory(SerializationFactory sf) {
233 channelInitializer.setSerializationFactory(sf);
239 public void setDeserializationFactory(DeserializationFactory factory) {
240 channelInitializer.setDeserializationFactory(factory);