/*
* Copyright 2009-2016 Weibo, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.weibo.api.motan.transport.netty;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.handler.codec.frame.FrameDecoder;
import com.weibo.api.motan.codec.Codec;
import com.weibo.api.motan.common.MotanConstants;
import com.weibo.api.motan.exception.MotanFrameworkException;
import com.weibo.api.motan.exception.MotanServiceException;
import com.weibo.api.motan.rpc.DefaultResponse;
import com.weibo.api.motan.rpc.Response;
import com.weibo.api.motan.util.LoggerUtil;
/**
* netty client decode
*
* @author maijunsheng
* @version 创建时间:2013-5-31
*
*/
public class NettyDecoder extends FrameDecoder {
private Codec codec;
private com.weibo.api.motan.transport.Channel client;
private int maxContentLength = 0;
public NettyDecoder(Codec codec, com.weibo.api.motan.transport.Channel client, int maxContentLength) {
this.codec = codec;
this.client = client;
this.maxContentLength = maxContentLength;
}
@Override
protected Object decode(ChannelHandlerContext ctx, Channel channel, ChannelBuffer buffer) throws Exception {
if (buffer.readableBytes() <= MotanConstants.NETTY_HEADER) {
return null;
}
buffer.markReaderIndex();
short type = buffer.readShort();
if (type != MotanConstants.NETTY_MAGIC_TYPE) {
buffer.resetReaderIndex();
throw new MotanFrameworkException("NettyDecoder transport header not support, type: " + type);
}
byte messageType = (byte) buffer.readShort();
long requestId = buffer.readLong();
int dataLength = buffer.readInt();
// FIXME 如果dataLength过大,可能导致问题
if (buffer.readableBytes() < dataLength) {
buffer.resetReaderIndex();
return null;
}
if (maxContentLength > 0 && dataLength > maxContentLength) {
LoggerUtil.warn(
"NettyDecoder transport data content length over of limit, size: {} > {}. remote={} local={}",
dataLength, maxContentLength, ctx.getChannel().getRemoteAddress(), ctx.getChannel()
.getLocalAddress());
Exception e = new MotanServiceException("NettyDecoder transport data content length over of limit, size: "
+ dataLength + " > " + maxContentLength);
if (messageType == MotanConstants.FLAG_REQUEST) {
Response response = buildExceptionResponse(requestId, e);
channel.write(response);
throw e;
} else {
throw e;
}
}
byte[] data = new byte[dataLength];
buffer.readBytes(data);
try {
String remoteIp = getRemoteIp(channel);
return codec.decode(client, remoteIp, data);
} catch (Exception e) {
if (messageType == MotanConstants.FLAG_REQUEST) {
Response resonse = buildExceptionResponse(requestId, e);
channel.write(resonse);
return null;
} else {
Response resonse = buildExceptionResponse(requestId, e);
return resonse;
}
}
}
private Response buildExceptionResponse(long requestId, Exception e) {
DefaultResponse response = new DefaultResponse();
response.setRequestId(requestId);
response.setException(e);
return response;
}
private String getRemoteIp(Channel channel) {
String ip = "";
SocketAddress remote = channel.getRemoteAddress();
if (remote != null) {
try {
ip = ((InetSocketAddress) remote).getAddress().getHostAddress();
} catch (Exception e) {
LoggerUtil.warn("get remoteIp error!dedault will use. msg:" + e.getMessage() + ", remote:" + remote.toString());
}
}
return ip;
}
}