com.taobao.api.internal.toplink.remoting.NettyRemotingDecoder Maven / Gradle / Ivy
package com.taobao.api.internal.toplink.remoting;
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.TooLongFrameException;
import org.jboss.netty.handler.codec.replay.ReplayingDecoder;
public class NettyRemotingDecoder extends ReplayingDecoder {
private NettyRemotingProtocolHandle handle;
private int payloadBytesRead;
private int payloadLength;
private ChannelBuffer payload;
public enum State {
HEADER, PAYLOAD
}
public NettyRemotingDecoder() {
super(State.HEADER);
}
@Override
protected Object decode(ChannelHandlerContext ctx, Channel channel, ChannelBuffer buffer, State state) throws Exception {
switch (state) {
case HEADER:
this.payloadBytesRead = 0;
this.payloadLength = -1;
this.payload = null;
this.handle = new NettyRemotingProtocolHandle(buffer);
this.handle.preamble = handle.ReadPreamble();
this.handle.majorVersion = handle.ReadMajorVersion();
this.handle.minorVersion = handle.ReadMinorVersion();
this.handle.operation = handle.ReadOperation();
this.handle.contentDelimiter = handle.ReadContentDelimiter();
this.handle.setContentLength(this.payloadLength = handle.ReadContentLength());
// not a good design that content-length do not contain headers
// length, so here read is blocked or maybe not read enought data
this.handle.transportHeaders = handle.ReadTransportHeaders();
checkpoint(State.PAYLOAD);
case PAYLOAD:
// refers to
// https://github.com/netty/netty/blob/netty-3.5.7.Final/src/main/java/org/jboss/netty/handler/codec/http/websocketx/WebSocket08FrameDecoder.java#L256
// Sometimes, the payload may not be delivered in 1 nice packet
// We need to accumulate the data until we have it all
int rbytes = this.actualReadableBytes();
ChannelBuffer payloadBuffer = null;
long willHaveReadByteCount = this.payloadBytesRead + rbytes;
if (willHaveReadByteCount == this.payloadLength) {
// We have all our content so proceed to process
payloadBuffer = buffer.readBytes(rbytes);
} else if (willHaveReadByteCount < this.payloadLength) {
// We don't have all our content so accumulate payload.
// Returning null means we will get called back
payloadBuffer = buffer.readBytes(rbytes);
if (this.payload == null)
this.payload = channel.getConfig().getBufferFactory().getBuffer(toFrameLength(this.payloadLength));
this.payload.writeBytes(payloadBuffer);
this.payloadBytesRead += rbytes;
// Return null to wait for more bytes to arrive
return null;
} else if (willHaveReadByteCount > this.payloadLength) {
// We have more than what we need so read up to the end of frame
// Leave the remainder in the buffer for next frame
payloadBuffer = buffer.readBytes(toFrameLength(this.payloadLength - this.payloadBytesRead));
}
checkpoint(State.HEADER);
if (this.payload == null)
this.payload = payloadBuffer;
else
this.payload.writeBytes(payloadBuffer);
this.handle.setContentBuffer(this.payload);
return this.handle;
default:
throw new Error("Shouldn't reach here.");
}
}
private static int toFrameLength(long l) throws TooLongFrameException {
if (l > Integer.MAX_VALUE) {
throw new TooLongFrameException("Length:" + l);
} else {
return (int) l;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy