/* * 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.buffer.ByteBuf; import io.netty.channel.Channel; import io.netty.channel.ChannelHandler.Sharable; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.channel.socket.DatagramPacket; import java.net.InetSocketAddress; import org.opendaylight.usc.manager.monitor.evt.UscSessionTransactionEvent; import org.opendaylight.usc.plugin.model.UscChannel; import org.opendaylight.usc.plugin.model.UscSessionImpl; import org.opendaylight.usc.protocol.UscData; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * This class takes all the inputs from the various client sessions and multiplexes them into the combined USC channel. */ @Sharable public class UscMultiplexer extends ChannelInboundHandlerAdapter { private static final Logger LOG = LoggerFactory.getLogger(UscMultiplexer.class); public static final int MAX_PAYLOAD_SIZE = 64512;// 63K private final UscPlugin plugin; /** * Constructs a new UscMultiplexer * * @param plugin * The instance of UscPlugin on whose behalf this demultiplexer is managing session state. */ public UscMultiplexer(UscPlugin plugin) { this.plugin = plugin; } @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { ByteBuf payload = (ByteBuf) msg; LOG.trace("UscMultiplexer.channelRead: " + payload); Channel ch = ctx.channel(); Channel outboundChannel = ch.attr(UscPlugin.DIRECT_CHANNEL).get(); if (outboundChannel != null) { if (plugin.getChannelType() == UscChannel.ChannelType.DTLS || plugin.getChannelType() == UscChannel.ChannelType.UDP) { DatagramPacket packet = new DatagramPacket(payload, (InetSocketAddress) outboundChannel.remoteAddress()); LOG.trace("UscMultiplexer.channelRead: convert payload to DatagramPacket " + packet); outboundChannel.write(packet); } else outboundChannel.write(msg); } else { UscSessionImpl session = ch.attr(UscPlugin.SESSION).get().get(); outboundChannel = session.getChannel().getChannel(); UscData reply = null; ByteBuf subPayload = null; int length = payload.readableBytes(); int bytesOut = length; int index = 0; int realLength = 0; while (length > 0) { realLength = (length > MAX_PAYLOAD_SIZE) ? MAX_PAYLOAD_SIZE : length; subPayload = payload.copy(index, realLength); index += realLength; length -= realLength; reply = new UscData(session.getPort(), session.getSessionId(), subPayload); LOG.trace("Send data to Java Agent " + reply); outboundChannel.writeAndFlush(reply); } plugin.sendEvent(new UscSessionTransactionEvent(session, 0, bytesOut)); } } @Override public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { LOG.trace("UscMultiplexer.channelReadComplete"); Channel ch = ctx.channel(); Channel outboundChannel = ch.attr(UscPlugin.DIRECT_CHANNEL).get(); if (outboundChannel != null) { outboundChannel.flush(); } else { UscSessionImpl session = ch.attr(UscPlugin.SESSION).get().get(); outboundChannel = session.getChannel().getChannel(); outboundChannel.flush(); } } }