/* * 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.UscRouteIdentifier; import org.opendaylight.usc.manager.cluster.message.UscRemoteDataMessage; import org.opendaylight.usc.util.UscServiceUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.channel.ChannelHandler.Sharable; import io.netty.util.ReferenceCountUtil; /** * This handler only for remote device, it will be added into the localServer * pipeline.this handler like a remote dummy device to process all of * communication with the remote device */ @Sharable public class UscRemoteDeviceHandler extends ChannelInboundHandlerAdapter { private static final Logger LOG = LoggerFactory.getLogger(UscRemoteDeviceHandler.class); private UscRouteBrokerService broker; private ByteBuf buffer = Unpooled.buffer(10000); private UscRouteIdentifier routeId; public UscRemoteDeviceHandler() { } private boolean isRemote(ChannelHandlerContext ctx) { routeId = ctx.channel().attr(UscPlugin.ROUTE_IDENTIFIER).get(); if (routeId != null) { LOG.trace("UscRemoteDeviceHandler:Channel read finished for route id(" + routeId + ")"); if (broker == null) { broker = UscServiceUtils.getService(UscRouteBrokerService.class); } if (broker != null) { if (broker.isLocalRemoteSession(routeId)) { return true; } else { LOG.debug("It's not local to remote channel(" + routeId + ") message, pass it to other handler"); } } else { LOG.error("Broker service is null! Can't check if it is remote channel message, and pass it to other handler."); } } return false; } @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { if (isRemote(ctx)) { ByteBuf payload = (ByteBuf) msg; byte[] data = getPayloadFromByteBuf(payload); writeBuffer(data); return; } ReferenceCountUtil.retain(msg); // propagate the data to rest of handlers in pipeline ctx.fireChannelRead(msg); } 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; } private void writeBuffer(byte[] data) { int newSize = 0; int oldSize = buffer.capacity(); int length = data.length; if (buffer.writableBytes() <= length) { if (length > oldSize) { newSize = length * 2; } else { newSize = 2 * oldSize; } buffer.capacity(newSize); } buffer.writeBytes(data); } @Override public void channelInactive(ChannelHandlerContext ctx) throws Exception { if (isRemote(ctx)) { broker.removeLocalSession(routeId); } ctx.fireChannelInactive(); } @Override public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { if (isRemote(ctx)) { byte[] data = getPayloadFromByteBuf(buffer); LOG.trace("Read complete,send message to remote channel: " + routeId + ",message is " + new String(data)); broker.sendRequest(new UscRemoteDataMessage(routeId, data, true)); buffer.clear(); return; } // propagate the data to rest of handlers in pipeline ctx.fireChannelReadComplete(); } }