/*
* 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 org.opendaylight.usc.manager.UscRouteBrokerService;
import org.opendaylight.usc.manager.cluster.UscRemoteChannelIdentifier;
import org.opendaylight.usc.manager.cluster.UscRouteIdentifier;
import org.opendaylight.usc.manager.cluster.message.UscRemoteChannelEventMessage;
import org.opendaylight.usc.plugin.exception.UscSessionException;
import org.opendaylight.usc.plugin.model.UscChannelImpl;
import org.opendaylight.usc.protocol.UscError;
import org.opendaylight.usc.protocol.UscFrame;
import org.opendaylight.usc.protocol.UscHeader;
import org.opendaylight.usc.util.UscServiceUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.ChannelHandler.Sharable;
import io.netty.channel.socket.DatagramPacket;
import io.netty.util.ReferenceCountUtil;
/**
* This class handles the device response for remote server,this handler like a
* remote dummy server
*/
@Sharable
public class UscRemoteServerHandler extends SimpleChannelInboundHandler<Object> {
private static final Logger LOG = LoggerFactory.getLogger(UscRemoteServerHandler.class);
private UscRouteBrokerService broker;
public UscRemoteServerHandler() {
}
@Override
protected void channelRead0(ChannelHandlerContext ctx, Object data) throws Exception {
UscRouteIdentifier localRouteId = null;
// get local route identifier
if (data instanceof UscFrame) {
LOG.trace("Read data from Usc Agent: " + data);
// communicate with agent
final UscHeader header = ((UscFrame) data).getHeader();
final UscChannelImpl connection = ctx.channel().attr(UscPlugin.CHANNEL).get();
// for remote session
localRouteId = new UscRouteIdentifier(connection.getDevice().getInetAddress(), connection.getType(),
header.getSessionId(), header.getApplicationPort());
} else {
LOG.trace("Read data from None Usc Agent: " + data);
// communicate directly with device
localRouteId = ctx.channel().attr(UscPlugin.ROUTE_IDENTIFIER).get();
}
if (broker == null) {
broker = UscServiceUtils.getService(UscRouteBrokerService.class);
}
if (broker == null) {
LOG.error("Broker service is null!Can't check if it is response from remote channel.Route id is "
+ localRouteId);
} else if (broker.isRemoteSession(localRouteId)) {
byte[] payload = null;
// get content, after reading the readable data become zero,can't
// use again
if (data instanceof UscFrame) {
payload = getPayloadFromByteBuf(((UscFrame) data).getPayload());
} else if (data instanceof DatagramPacket) {
payload = getPayloadFromByteBuf(((DatagramPacket) data).content());
} else {
payload = getPayloadFromByteBuf((ByteBuf) data);
}
if (data instanceof UscError) {
// propagate exception to the client channel
UscSessionException ex = new UscSessionException(((UscError) data).getErrorCode());
// send error message back to remote request controller
broker.sendException(localRouteId, ex);
} else {
broker.sendResponse(localRouteId, payload);
}
LOG.trace("It is response from local remote channel.Sending message to route id (" + localRouteId
+ ").messsage is " + new String(payload));
return;
}
ReferenceCountUtil.retain(data);
// propagate the data to rest of handlers in pipeline
ctx.fireChannelRead(data);
}
private byte[] getPayloadFromByteBuf(ByteBuf buf) {
int length = buf.readableBytes();
byte[] ret = new byte[length];
for (int i = 0; i < length; i++) {
ret[i] = buf.readByte();
}
return ret;
}
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
LOG.trace("UscRemoteServerHandler channelInactive()");
if (broker == null) {
broker = UscServiceUtils.getService(UscRouteBrokerService.class);
}
if (broker == null) {
LOG.warn("Broker service is null!Can't broadcast the channel close event to all other remote controller in cluster.");
} else {
UscRemoteChannelIdentifier remoteChannel = null;
final UscChannelImpl connection = ctx.channel().attr(UscPlugin.CHANNEL).get();
if (connection != null) {
remoteChannel = new UscRemoteChannelIdentifier(connection.getDevice().getInetAddress(),
connection.getType());
} else {
// communicate directly with device
UscRouteIdentifier localRouteId = ctx.channel().attr(UscPlugin.ROUTE_IDENTIFIER).get();
if (localRouteId != null) {
remoteChannel = localRouteId;
}
}
if (remoteChannel != null) {
UscRemoteChannelEventMessage message = new UscRemoteChannelEventMessage(remoteChannel,
UscRemoteChannelEventMessage.ChannelEventType.CLOSE);
broker.broadcastMessage(message);
}
}
ctx.fireChannelInactive();
}
}