/** * This file is part of Waarp Project. * * Copyright 2009, Frederic Bregier, and individual contributors by the @author tags. See the * COPYRIGHT.txt in the distribution for a full listing of individual contributors. * * All Waarp Project is free software: you can redistribute it and/or modify it under the terms of * the GNU General Public License as published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. * * Waarp is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General * Public License for more details. * * You should have received a copy of the GNU General Public License along with Waarp . If not, see * <http://www.gnu.org/licenses/>. */ package org.waarp.openr66.protocol.localhandler; import static org.waarp.openr66.context.R66FiniteDualStates.ERROR; import io.netty.channel.Channel; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.SimpleChannelInboundHandler; import org.waarp.common.logging.WaarpLogger; import org.waarp.common.logging.WaarpLoggerFactory; import org.waarp.openr66.context.ErrorCode; import org.waarp.openr66.context.R66Result; import org.waarp.openr66.protocol.configuration.Configuration; import org.waarp.openr66.protocol.exception.OpenR66Exception; import org.waarp.openr66.protocol.exception.OpenR66ExceptionTrappedFactory; import org.waarp.openr66.protocol.exception.OpenR66ProtocolBusinessNoWriteBackException; import org.waarp.openr66.protocol.exception.OpenR66ProtocolNetworkException; import org.waarp.openr66.protocol.exception.OpenR66ProtocolNoConnectionException; import org.waarp.openr66.protocol.exception.OpenR66ProtocolShutdownException; import org.waarp.openr66.protocol.exception.OpenR66ProtocolSystemException; import org.waarp.openr66.protocol.localhandler.packet.AbstractLocalPacket; import org.waarp.openr66.protocol.localhandler.packet.ErrorPacket; import org.waarp.openr66.protocol.localhandler.packet.LocalPacketFactory; import org.waarp.openr66.protocol.utils.ChannelCloseTimer; import org.waarp.openr66.protocol.utils.ChannelUtils; /** * @author frederic bregier */ class LocalClientHandler extends SimpleChannelInboundHandler<AbstractLocalPacket> { /** * Internal Logger */ private static final WaarpLogger logger = WaarpLoggerFactory.getLogger(LocalClientHandler.class); /** * Local Channel Reference */ private volatile LocalChannelReference localChannelReference = null; @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { logger.debug("Local Client Channel Connected: " + ctx.channel().id()); } @Override public void channelInactive(ChannelHandlerContext ctx) throws Exception { logger.debug("Local Client Channel Closed: {}", ctx.channel().id()); } /** * Initiate the LocalChannelReference * * @param channel * @throws InterruptedException * @throws OpenR66ProtocolNetworkException */ private void initLocalClientHandler(Channel channel) throws InterruptedException, OpenR66ProtocolNetworkException { int i = 0; if (localChannelReference == null) { for (i = 0; i < Configuration.RETRYNB; i++) { localChannelReference = Configuration.configuration .getLocalTransaction().getFromId(channel.id().hashCode()); if (localChannelReference != null) { return; } Thread.sleep(Configuration.RETRYINMS); Thread.yield(); } logger.warn("Cannot find local connection"); } } @Override protected void channelRead0(ChannelHandlerContext ctx, AbstractLocalPacket msg) throws Exception { if (localChannelReference == null) { initLocalClientHandler(ctx.channel()); } // only Startup Packet should arrived here ! final AbstractLocalPacket packet = msg; if (packet.getType() != LocalPacketFactory.STARTUPPACKET) { logger.error("Local Client Channel Recv wrong packet: " + ctx.channel().id() + " : " + packet.toString()); throw new OpenR66ProtocolSystemException("Should not be here: Wrong packet received {" + packet.toString() + "}"); } logger.debug("LocalClientHandler initialized: " + (localChannelReference != null)); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { // informs network of the problem Channel channel = ctx.channel(); logger.debug( "Local Client Channel Exception: {}", channel.id(), cause); if (localChannelReference == null) { initLocalClientHandler(channel); } if (localChannelReference != null) { OpenR66Exception exception = OpenR66ExceptionTrappedFactory .getExceptionFromTrappedException(channel, cause); localChannelReference.sessionNewState(ERROR); if (exception != null) { if (exception instanceof OpenR66ProtocolShutdownException) { ChannelUtils.startShutdown(); /* * Dont close, thread will do logger.debug("Will close channel"); Channels.close(e.channel()); */ return; } else if (exception instanceof OpenR66ProtocolBusinessNoWriteBackException) { logger.error("Will close channel", exception); channel.close(); return; } else if (exception instanceof OpenR66ProtocolNoConnectionException) { logger.error("Will close channel", exception); channel.close(); return; } final ErrorPacket errorPacket = new ErrorPacket(exception .getMessage(), ErrorCode.RemoteError.getCode(), ErrorPacket.FORWARDCLOSECODE); ChannelUtils.writeAbstractLocalPacket(localChannelReference, errorPacket, true); if (!localChannelReference.getFutureRequest().isDone()) { localChannelReference.invalidateRequest(new R66Result( exception, localChannelReference.getSession(), true, ErrorCode.Internal, null)); } } else { // Nothing to do return; } } logger.debug("Will close channel"); ChannelCloseTimer.closeFutureChannel(channel); } }