Make CompatibleMarshallingDecoder discard the inbound buffer once TooLongFrameException is raised

(See #768)

Once too long object is received, CompatibleMarshallingDecoder has to
discard all input from now on, just like MarshallingDecoder does.
Otherwise, the decoder will raise more exceptions because the decoder
has no idea anymore where the object starts.

Before this fix, SerialThreadLocalCompatibleMarshallingDecoderTest
logged many additional exceptions raised by the decoder after test is
finished.
This commit is contained in:
Trustin Lee 2012-11-26 14:38:20 +09:00
parent d7d8503f5c
commit 5b68f00382

View File

@ -20,12 +20,11 @@ import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ReplayingDecoder;
import io.netty.handler.codec.TooLongFrameException;
import java.io.ObjectStreamConstants;
import org.jboss.marshalling.ByteInput;
import org.jboss.marshalling.Unmarshaller;
import java.io.ObjectStreamConstants;
/**
* {@link ReplayingDecoder} which use an {@link Unmarshaller} to read the Object out of the {@link ByteBuf}.
*
@ -34,6 +33,7 @@ import org.jboss.marshalling.Unmarshaller;
public class CompatibleMarshallingDecoder extends ReplayingDecoder<Object, Void> {
protected final UnmarshallerProvider provider;
protected final int maxObjectSize;
private boolean discardingTooLongFrame;
/**
* Create a new instance of {@link CompatibleMarshallingDecoder}.
@ -55,17 +55,24 @@ public class CompatibleMarshallingDecoder extends ReplayingDecoder<Object, Void>
@Override
public Object decode(ChannelHandlerContext ctx, ByteBuf buffer) throws Exception {
if (discardingTooLongFrame) {
buffer.skipBytes(actualReadableBytes());
checkpoint();
return null;
}
Unmarshaller unmarshaller = provider.getUnmarshaller(ctx);
ByteInput input = new ChannelBufferByteInput(buffer);
if (maxObjectSize != Integer.MAX_VALUE) {
input = new LimitingByteInput(input, maxObjectSize);
}
}768
try {
unmarshaller.start(input);
Object obj = unmarshaller.readObject();
unmarshaller.finish();
return obj;
} catch (LimitingByteInput.TooBigObjectException e) {
discardingTooLongFrame = true;
throw new TooLongFrameException("Object to big to unmarshal");
} finally {
// Call close in a finally block as the ReplayingDecoder will throw an Error if not enough bytes are