/** * Creates a LengthFieldBasedFrameDecoder where the first 8 bytes are the length of the frame. * This is used before all decoders. */ public static TransportFrameDecoder createFrameDecoder() { return new TransportFrameDecoder(); }
private ByteBuf decodeNext() throws Exception { long frameSize = decodeFrameSize(); if (frameSize == UNKNOWN_FRAME_SIZE || totalSize < frameSize) { return null; } // Reset size for next frame. nextFrameSize = UNKNOWN_FRAME_SIZE; Preconditions.checkArgument(frameSize < MAX_FRAME_SIZE, "Too large frame: %s", frameSize); Preconditions.checkArgument(frameSize > 0, "Frame length should be positive: %s", frameSize); // If the first buffer holds the entire frame, return it. int remaining = (int) frameSize; if (buffers.getFirst().readableBytes() >= remaining) { return nextBufferForFrame(remaining); } // Otherwise, create a composite buffer. CompositeByteBuf frame = buffers.getFirst().alloc().compositeBuffer(Integer.MAX_VALUE); while (remaining > 0) { ByteBuf next = nextBufferForFrame(remaining); remaining -= next.readableBytes(); frame.addComponent(next).writerIndex(frame.writerIndex() + next.readableBytes()); } assert remaining == 0; return frame; }
@Override public void channelRead(ChannelHandlerContext ctx, Object data) throws Exception { ByteBuf in = (ByteBuf) data; buffers.add(in); totalSize += in.readableBytes(); while (!buffers.isEmpty()) { // First, feed the interceptor, and if it's still, active, try again. if (interceptor != null) { ByteBuf first = buffers.getFirst(); int available = first.readableBytes(); if (feedInterceptor(first)) { assert !first.isReadable() : "Interceptor still active but buffer has data."; } int read = available - first.readableBytes(); if (read == available) { buffers.removeFirst().release(); } totalSize -= read; } else { // Interceptor is not active, so try to decode one frame. ByteBuf frame = decodeNext(); if (frame == null) { break; } ctx.fireChannelRead(frame); } } }
@Test public void testInterception() throws Exception { int interceptedReads = 3; TransportFrameDecoder decoder = new TransportFrameDecoder(); TransportFrameDecoder.Interceptor interceptor = spy(new MockInterceptor(interceptedReads)); ChannelHandlerContext ctx = mockChannelHandlerContext(); byte[] data = new byte[8]; ByteBuf len = Unpooled.copyLong(8 + data.length); ByteBuf dataBuf = Unpooled.wrappedBuffer(data); try { decoder.setInterceptor(interceptor); for (int i = 0; i < interceptedReads; i++) { decoder.channelRead(ctx, dataBuf); assertEquals(0, dataBuf.refCnt()); dataBuf = Unpooled.wrappedBuffer(data); } decoder.channelRead(ctx, len); decoder.channelRead(ctx, dataBuf); verify(interceptor, times(interceptedReads)).handle(any(ByteBuf.class)); verify(ctx).fireChannelRead(any(ByteBuf.class)); assertEquals(0, len.refCnt()); assertEquals(0, dataBuf.refCnt()); } finally { release(len); release(dataBuf); } }
TransportFrameDecoder frameDecoder = (TransportFrameDecoder) channel.pipeline().get(TransportFrameDecoder.HANDLER_NAME); frameDecoder.setInterceptor(interceptor); streamActive = true; } catch (Exception e) {
@Test public void testSplitLengthField() throws Exception { byte[] frame = new byte[1024 * (RND.nextInt(31) + 1)]; ByteBuf buf = Unpooled.buffer(frame.length + 8); buf.writeLong(frame.length + 8); buf.writeBytes(frame); TransportFrameDecoder decoder = new TransportFrameDecoder(); ChannelHandlerContext ctx = mockChannelHandlerContext(); try { decoder.channelRead(ctx, buf.readSlice(RND.nextInt(7)).retain()); verify(ctx, never()).fireChannelRead(any(ByteBuf.class)); decoder.channelRead(ctx, buf); verify(ctx).fireChannelRead(any(ByteBuf.class)); assertEquals(0, buf.refCnt()); } finally { decoder.channelInactive(ctx); release(buf); } }
private void testInvalidFrame(long size) throws Exception { TransportFrameDecoder decoder = new TransportFrameDecoder(); ChannelHandlerContext ctx = mock(ChannelHandlerContext.class); ByteBuf frame = Unpooled.copyLong(size); try { decoder.channelRead(ctx, frame); } finally { release(frame); } }
private void verifyAndCloseDecoder( TransportFrameDecoder decoder, ChannelHandlerContext ctx, ByteBuf data) throws Exception { try { decoder.channelInactive(ctx); assertTrue("There shouldn't be dangling references to the data.", data.release()); } finally { release(data); } }
/** * Creates a number of randomly sized frames and feed them to the given decoder, verifying * that the frames were read. */ private ByteBuf createAndFeedFrames( int frameCount, TransportFrameDecoder decoder, ChannelHandlerContext ctx) throws Exception { ByteBuf data = Unpooled.buffer(); for (int i = 0; i < frameCount; i++) { byte[] frame = new byte[1024 * (RND.nextInt(31) + 1)]; data.writeLong(frame.length + 8); data.writeBytes(frame); } try { while (data.isReadable()) { int size = RND.nextInt(4 * 1024) + 256; decoder.channelRead(ctx, data.readSlice(Math.min(data.readableBytes(), size)).retain()); } verify(ctx, times(frameCount)).fireChannelRead(any(ByteBuf.class)); } catch (Exception e) { release(data); throw e; } return data; }
@Test public void testInterception() throws Exception { int interceptedReads = 3; TransportFrameDecoder decoder = new TransportFrameDecoder(); TransportFrameDecoder.Interceptor interceptor = spy(new MockInterceptor(interceptedReads)); ChannelHandlerContext ctx = mockChannelHandlerContext(); byte[] data = new byte[8]; ByteBuf len = Unpooled.copyLong(8 + data.length); ByteBuf dataBuf = Unpooled.wrappedBuffer(data); try { decoder.setInterceptor(interceptor); for (int i = 0; i < interceptedReads; i++) { decoder.channelRead(ctx, dataBuf); assertEquals(0, dataBuf.refCnt()); dataBuf = Unpooled.wrappedBuffer(data); } decoder.channelRead(ctx, len); decoder.channelRead(ctx, dataBuf); verify(interceptor, times(interceptedReads)).handle(any(ByteBuf.class)); verify(ctx).fireChannelRead(any(ByteBuffer.class)); assertEquals(0, len.refCnt()); assertEquals(0, dataBuf.refCnt()); } finally { release(len); release(dataBuf); } }
TransportFrameDecoder frameDecoder = (TransportFrameDecoder) channel.pipeline().get(TransportFrameDecoder.HANDLER_NAME); frameDecoder.setInterceptor(interceptor); streamActive = true; } catch (Exception e) {
@Test public void testSplitLengthField() throws Exception { byte[] frame = new byte[1024 * (RND.nextInt(31) + 1)]; ByteBuf buf = Unpooled.buffer(frame.length + 8); buf.writeLong(frame.length + 8); buf.writeBytes(frame); TransportFrameDecoder decoder = new TransportFrameDecoder(); ChannelHandlerContext ctx = mockChannelHandlerContext(); try { decoder.channelRead(ctx, buf.readSlice(RND.nextInt(7)).retain()); verify(ctx, never()).fireChannelRead(any(ByteBuf.class)); decoder.channelRead(ctx, buf); verify(ctx).fireChannelRead(any(ByteBuf.class)); assertEquals(0, buf.refCnt()); } finally { decoder.channelInactive(ctx); release(buf); } }
private void testInvalidFrame(long size) throws Exception { TransportFrameDecoder decoder = new TransportFrameDecoder(); ChannelHandlerContext ctx = mock(ChannelHandlerContext.class); ByteBuf frame = Unpooled.copyLong(size); try { decoder.channelRead(ctx, frame); } finally { release(frame); } }
private void verifyAndCloseDecoder( TransportFrameDecoder decoder, ChannelHandlerContext ctx, ByteBuf data) throws Exception { try { decoder.channelInactive(ctx); assertTrue("There shouldn't be dangling references to the data.", data.release()); } finally { release(data); } }
/** * Creates a number of randomly sized frames and feed them to the given decoder, verifying * that the frames were read. */ private ByteBuf createAndFeedFrames( int frameCount, TransportFrameDecoder decoder, ChannelHandlerContext ctx) throws Exception { ByteBuf data = Unpooled.buffer(); for (int i = 0; i < frameCount; i++) { byte[] frame = new byte[1024 * (RND.nextInt(31) + 1)]; data.writeLong(frame.length + 8); data.writeBytes(frame); } try { while (data.isReadable()) { int size = RND.nextInt(4 * 1024) + 256; decoder.channelRead(ctx, data.readSlice(Math.min(data.readableBytes(), size)).retain()); } verify(ctx, times(frameCount)).fireChannelRead(any(ByteBuf.class)); } catch (Exception e) { release(data); throw e; } return data; }
/** * Creates a LengthFieldBasedFrameDecoder where the first 8 bytes are the length of the frame. * This is used before all decoders. */ public static TransportFrameDecoder createFrameDecoder() { return new TransportFrameDecoder(); }
private ByteBuf decodeNext() { long frameSize = decodeFrameSize(); if (frameSize == UNKNOWN_FRAME_SIZE || totalSize < frameSize) { return null; } // Reset size for next frame. nextFrameSize = UNKNOWN_FRAME_SIZE; Preconditions.checkArgument(frameSize < MAX_FRAME_SIZE, "Too large frame: %s", frameSize); Preconditions.checkArgument(frameSize > 0, "Frame length should be positive: %s", frameSize); // If the first buffer holds the entire frame, return it. int remaining = (int) frameSize; if (buffers.getFirst().readableBytes() >= remaining) { return nextBufferForFrame(remaining); } // Otherwise, create a composite buffer. CompositeByteBuf frame = buffers.getFirst().alloc().compositeBuffer(Integer.MAX_VALUE); while (remaining > 0) { ByteBuf next = nextBufferForFrame(remaining); remaining -= next.readableBytes(); frame.addComponent(next).writerIndex(frame.writerIndex() + next.readableBytes()); } assert remaining == 0; return frame; }
@Override public void channelRead(ChannelHandlerContext ctx, Object data) throws Exception { ByteBuf in = (ByteBuf) data; buffers.add(in); totalSize += in.readableBytes(); while (!buffers.isEmpty()) { // First, feed the interceptor, and if it's still, active, try again. if (interceptor != null) { ByteBuf first = buffers.getFirst(); int available = first.readableBytes(); if (feedInterceptor(first)) { assert !first.isReadable() : "Interceptor still active but buffer has data."; } int read = available - first.readableBytes(); if (read == available) { buffers.removeFirst().release(); } totalSize -= read; } else { // Interceptor is not active, so try to decode one frame. ByteBuf frame = decodeNext(); if (frame == null) { break; } ctx.fireChannelRead(frame); } } }
TransportFrameDecoder frameDecoder = (TransportFrameDecoder) channel.pipeline().get(TransportFrameDecoder.HANDLER_NAME); frameDecoder.setInterceptor(interceptor); streamActive = true; } catch (Exception e) {
/** * Creates a LengthFieldBasedFrameDecoder where the first 8 bytes are the length of the frame. * This is used before all decoders. */ public static TransportFrameDecoder createFrameDecoder() { return new TransportFrameDecoder(); }