/* * Copyright (c) 2015 Huawei, Inc and others. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 which accompanies this distribution, * and is available at http://www.eclipse.org/legal/epl-v10.html */ package org.opendaylight.usc.plugin; import io.netty.bootstrap.Bootstrap; import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandler; import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelOutboundHandler; import io.netty.channel.ChannelPipeline; import io.netty.channel.EventLoopGroup; import io.netty.channel.local.LocalAddress; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.DatagramPacket; import io.netty.channel.socket.nio.NioDatagramChannel; import io.netty.handler.logging.LogLevel; import io.netty.handler.logging.LoggingHandler; import java.net.InetSocketAddress; import javax.net.ssl.SSLException; import org.opendaylight.usc.manager.UscRouteBrokerService; import org.opendaylight.usc.manager.api.UscConfigurationService; import org.opendaylight.usc.manager.api.UscSecureService; import org.opendaylight.usc.plugin.model.UscChannel.ChannelType; import org.opendaylight.usc.plugin.model.UscDevice; import org.opendaylight.usc.util.UscServiceUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * UscPlugin implemented for UDP traffic. */ public class UscPluginUdp extends UscPlugin { private static final Logger log = LoggerFactory .getLogger(UscPluginUdp.class); private final UscSecureService secureService; private final UscConfigurationService configService; private final EventLoopGroup agentGroup = new NioEventLoopGroup(); private final Bootstrap agentBootstrap = new Bootstrap(); private Bootstrap directBootstrap = null; private EventLoopGroup directGroup = null; private final ChannelInboundHandlerAdapter callHomeHandler = new ChannelInboundHandlerAdapter() { @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { final Channel ch = ctx.channel(); final InetSocketAddress remoteAddress = ((DatagramPacket) msg) .sender(); // this is to deal with UDP channels which don't by default have // remote address if (ch.remoteAddress() == null) { ch.connect(remoteAddress); } addCallHomeConnection(remoteAddress, ch); super.channelRead(ctx, msg); ch.pipeline().remove(this); } }; /** * Constructs a new UscPluginUdp */ public UscPluginUdp() { super(new LocalAddress("usc-local-server-udp")); UscRouteBrokerService routeBroker = UscServiceUtils .getService(UscRouteBrokerService.class); if (routeBroker != null) { routeBroker.setConnetionManager(ChannelType.UDP, super.getConnectionManager()); routeBroker.setConnetionManager(ChannelType.DTLS, super.getConnectionManager()); } else { log.error("UscRouteBrokerService is not found, failed to set connection manager for all UDP Channel!"); } configService = UscServiceUtils .getService(UscConfigurationService.class); secureService = UscServiceUtils.getService(UscSecureService.class); agentBootstrap.group(agentGroup); agentBootstrap.channel(NioDatagramChannel.class); agentBootstrap.handler(new ChannelInitializer<Channel>() { @Override public void initChannel(final Channel ch) throws Exception { if (secureService == null) { log.error("UscSecureService is not initialized!"); return; } ChannelPipeline p = ch.pipeline(); ChannelHandler dtlsHandler = secureService .getUdpClientHandler(ch); initAgentPipeline(p, dtlsHandler); } }); final Bootstrap callHomeServerUdpBootstrap = new Bootstrap(); callHomeServerUdpBootstrap.group(agentGroup); callHomeServerUdpBootstrap.channel(NioDatagramChannel.class); callHomeServerUdpBootstrap .handler(new ChannelInitializer<NioDatagramChannel>() { @Override public void initChannel(final NioDatagramChannel ch) throws Exception { if (secureService == null) { log.error("UscSecureService is not initialized!"); return; } ChannelPipeline p = ch.pipeline(); // no remoteAddress yet until data received, so need a // handler // to add the channel p.addLast("callHomeHandler", callHomeHandler); p.addLast(new LoggingHandler(LogLevel.TRACE)); ChannelHandler dtlsHandler = secureService .getUdpServerHandler(ch); initAgentPipeline(ch.pipeline(), dtlsHandler); } }); if (configService == null) { log.error("UscConfigurationService is not initialized!"); return; } int pluginPort = configService .getConfigIntValue(UscConfigurationService.USC_PLUGIN_PORT); final ChannelFuture callHomeChannelUdpFuture = callHomeServerUdpBootstrap .bind(pluginPort); log.debug("callHomeChannelUdpFuture : " + callHomeChannelUdpFuture); try { callHomeChannelUdpFuture.sync(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } @Override protected ChannelOutboundHandler getFrameEncoder() { return UscFrameEncoderUdp.getInstance(); } @Override protected ChannelInboundHandler getFrameDecoder() { return UscFrameDecoderUdp.getInstance(); } @Override public void close() { super.close(); agentGroup.shutdownGracefully(); if (directGroup != null) directGroup.shutdownGracefully(); } @Override protected Channel connectToAgent(UscDevice device) throws InterruptedException { if (configService == null) { log.error("UscConfigurationService is not initialized!"); return null; } final int agentPort = configService .getConfigIntValue(UscConfigurationService.USC_AGENT_PORT); Channel channel = null; try { channel = agentBootstrap .connect(device.getInetAddress(), agentPort).sync() .channel(); } catch (InterruptedException e) { throw e; } return channel; } @Override protected Channel connectToDeviceDirectly(UscDevice device) throws Exception { Channel channel = null; if (directBootstrap == null) { directBootstrap = new Bootstrap(); directGroup = new NioEventLoopGroup(); directBootstrap.group(directGroup); directBootstrap.channel(NioDatagramChannel.class); directBootstrap.handler(new ChannelInitializer<Channel>() { @Override public void initChannel(final Channel ch) throws Exception { if (secureService == null) { log.error("UscSecureService is not initialized!"); return; } ChannelPipeline p = ch.pipeline(); ChannelHandler dtlsHandler = secureService .getUdpClientHandler(ch); initDirectPipeline(p, dtlsHandler); } }); } try { channel = directBootstrap .connect(device.getInetAddress(), device.getPort()).sync() .channel(); } catch (Exception e) { throw e; } return channel; } @Override protected ChannelType getChannelType() { return ChannelType.DTLS; } /** * Returns the security handler for server-side use. Currently this is DTLS. * * @param ch * The physical channel that the traffic will be sent through. * @return The channel handler, or null if the security service was not * properly initialized. * @throws SSLException */ public static ChannelHandler getSecureServerHandler(Channel ch) throws SSLException { UscSecureService service = UscServiceUtils.getService(UscSecureService.class); if (service == null) { log.error("UscSecureService is not initialized!"); return null; } return service.getUdpServerHandler(ch); } /** * Returns the security handler for client-side use. Currently this is DTLS. * * @param ch * The physical channel that the traffic will be sent through. * @return The channel handler, or null if the security service was not * properly initialized. * @throws SSLException */ public static ChannelHandler getSecureClientHandler(Channel ch) throws SSLException { UscSecureService service = UscServiceUtils.getService(UscSecureService.class); if (service == null) { log.error("UscSecureService is not initialized!"); return null; } return service.getUdpClientHandler(ch); } }