package com.baidu.beidou.navi.pbrpc.client.handler; import io.netty.channel.Channel; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.SimpleChannelInboundHandler; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.baidu.beidou.navi.pbrpc.client.callback.Callback; import com.baidu.beidou.navi.pbrpc.client.callback.CallbackContext; import com.baidu.beidou.navi.pbrpc.client.callback.CallbackPool; import com.baidu.beidou.navi.pbrpc.codec.Codec; import com.baidu.beidou.navi.pbrpc.codec.impl.ProtobufCodec; import com.baidu.beidou.navi.pbrpc.error.ExceptionUtil; import com.baidu.beidou.navi.pbrpc.transport.PbrpcMessageDeserializer; import com.baidu.beidou.navi.pbrpc.transport.PbrpcMsg; import com.baidu.beidou.navi.pbrpc.util.ContextHolder; import com.baidu.beidou.navi.pbrpc.util.Preconditions; import com.google.protobuf.GeneratedMessage; /** * ClassName: PbrpcClientHandler <br/> * Function: 客户端的核心handler * * @author Zhang Xu */ public class PbrpcClientHandler extends SimpleChannelInboundHandler<PbrpcMsg> { private static final Logger LOG = LoggerFactory.getLogger(PbrpcMessageDeserializer.class); /** * 可配置,默认使用protobuf来做body的序列化 */ private Codec codec = new ProtobufCodec(); /** * @see io.netty.channel.SimpleChannelInboundHandler#channelRead0(io.netty.channel.ChannelHandlerContext, * java.lang.Object) */ @SuppressWarnings("unchecked") @Override public void channelRead0(ChannelHandlerContext ctx, PbrpcMsg pbrpcMsg) throws Exception { Preconditions .checkArgument(pbrpcMsg != null, "Pbrpc msg is null which should never happen"); try { // LOG.info("Got msg from server:" + pbrpcMsg); int logId = (int) pbrpcMsg.getLogId(); CallbackContext context = CallbackPool.getContext(logId); if (context == null) { LOG.warn("Receive msg from server but no context found, logId=" + logId); return; } Callback<GeneratedMessage> cb = (Callback<GeneratedMessage>) context.getCallback(); if (pbrpcMsg.getErrorCode() != null) { cb.handleError(ExceptionUtil.buildFromErrorCode(pbrpcMsg.getErrorCode())); } else { GeneratedMessage res = (GeneratedMessage) codec.decode( CallbackPool.getResClass(logId), pbrpcMsg.getData()); cb.handleResult(res); } // 短连接则关闭channel if (context.isShortAliveConn()) { Channel channel = context.getChannel(); if (channel != null) { LOG.info("Close " + channel + ", logId=" + logId); channel.close(); } } // LOG.info("Decoding and invoking callback " + pbrpcMsg.getLogId() + " total " // + (System.currentTimeMillis() - context.getStarttime()) // + "ms, transport using " + (start - context.getStarttime()) + "ms"); } finally { CallbackPool.remove((int) pbrpcMsg.getLogId()); ContextHolder.clean(); // ctx.fireChannelReadComplete(); } } /** * @see io.netty.channel.ChannelInboundHandlerAdapter#channelReadComplete(io.netty.channel.ChannelHandlerContext) */ @Override public void channelReadComplete(ChannelHandlerContext ctx) { // LOG.debug("Client channelReadComplete>>>>>"); // ctx.flush(); } /** * @see io.netty.channel.ChannelInboundHandlerAdapter#channelActive(io.netty.channel.ChannelHandlerContext) */ @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { // LOG.debug("Client channelActive>>>>>"); } /** * @see io.netty.channel.ChannelInboundHandlerAdapter#exceptionCaught(io.netty.channel.ChannelHandlerContext, * java.lang.Throwable) */ @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { LOG.error(cause.getMessage(), cause); ctx.close(); // FIXME // ctx.fireChannelRead(); } }