private void encodeChunkedContent( ChannelHandlerContext ctx, Object msg, int contentLength, List<Object> out) { if (contentLength > 0) { byte[] length = Integer.toHexString(contentLength).getBytes(CharsetUtil.US_ASCII); ByteBuf buf = ctx.alloc().buffer(length.length + 2); buf.writeBytes(length); buf.writeBytes(CRLF); out.add(buf); out.add(encodeAndRetain(msg)); out.add(CRLF_BUF.duplicate()); } if (msg instanceof LastHttpContent) { HttpHeaders headers = ((LastHttpContent) msg).trailingHeaders(); if (headers.isEmpty()) { out.add(ZERO_CRLF_CRLF_BUF.duplicate()); } else { ByteBuf buf = ctx.alloc().buffer(); buf.writeBytes(ZERO_CRLF); HttpHeaders.encode(headers, buf); buf.writeBytes(CRLF); out.add(buf); } state = ST_INIT; } else { if (contentLength == 0) { // Need to produce some output otherwise an // IllegalstateException will be thrown out.add(EMPTY_BUFFER); } } }
private void generateTraffic() { // Flush the outbound buffer to the socket. // Once flushed, generate the same amount of traffic again. ctx.writeAndFlush(content.duplicate().retain()).addListener(trafficGenerator); this.round++; }
@Override public byte[] allBytes() { ByteBuf dup = buf.duplicate().resetReaderIndex(); byte[] res = new byte[dup.readableBytes()]; dup.readBytes(res); return res; }
@Override public FullBinaryMemcacheResponse duplicate() { ByteBuf extras = getExtras(); if (extras != null) { extras = extras.duplicate(); } return new DefaultFullBinaryMemcacheResponse(getKey(), extras, content().duplicate()); }
@Override public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception { if (evt instanceof IdleStateEvent) { ctx.writeAndFlush(HEARTBEAT_SEQUENCE.duplicate()) .addListener(ChannelFutureListener.CLOSE_ON_FAILURE); } else { super.userEventTriggered(ctx, evt); } }
@Override public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception { if (evt instanceof IdleStateEvent) { IdleStateEvent event = (IdleStateEvent) evt; if (event.state().equals(IdleState.READER_IDLE)) { System.out.println("READER_IDLE"); NettyChannelMap.remove(ctx.channel()); ctx.writeAndFlush(HEARTBEAT_SEQUENCE.duplicate()).addListener(ChannelFutureListener.CLOSE); } else if (event.state().equals(IdleState.WRITER_IDLE)) { System.out.println("WRITER_IDLE"); } else if (event.state().equals(IdleState.ALL_IDLE)) { System.out.println("ALL_IDLE"); NettyChannelMap.remove(ctx.channel()); ctx.writeAndFlush(HEARTBEAT_SEQUENCE.duplicate()).addListener(ChannelFutureListener.CLOSE); } } else { super.userEventTriggered(ctx, evt); } }
@Override public synchronized ByteBuf readContent(ByteBufAllocator alloc) throws IOException { if (cachedContent == null) { final ByteBuf newContent = e.readContent(alloc); if (newContent.readableBytes() > maxCacheEntrySizeBytes) { // Do not cache if the content is too large. return newContent; } cachedContent = newContent; } return cachedContent.duplicate().retain(); }
private static void assertWriteFails(ChannelHandler handler, int count) { final ByteBuf buffer = Unpooled.copiedBuffer("Test", CharsetUtil.US_ASCII); final EmbeddedChannel channel = new EmbeddedChannel(handler); ByteBuf[] buffers = new ByteBuf[count]; for (int i = 0; i < buffers.length; i++) { buffers[i] = buffer.duplicate().retain(); } try { Assert.assertFalse(channel.writeOutbound(buffers)); Assert.fail(); } catch (Exception e) { Assert.assertTrue(e instanceof TestException); } Assert.assertFalse(channel.finish()); channel.closeFuture().syncUninterruptibly(); buffer.release(); Assert.assertNull(channel.readOutbound()); }
private static void assertWrite(ChannelHandler handler, int count) { final ByteBuf buffer = Unpooled.copiedBuffer("Test", CharsetUtil.US_ASCII); final EmbeddedChannel channel = new EmbeddedChannel(handler); channel.config().setWriteBufferLowWaterMark(1); channel.config().setWriteBufferHighWaterMark(3); ByteBuf[] buffers = new ByteBuf[count]; for (int i = 0; i < buffers.length; i++) { buffers[i] = buffer.duplicate().retain(); } Assert.assertTrue(channel.writeOutbound(buffers)); Assert.assertTrue(channel.finish()); channel.closeFuture().syncUninterruptibly(); for (int i = 0; i < buffers.length; i++) { assertBuffer(channel, buffer); } buffer.release(); Assert.assertNull(channel.readOutbound()); }
@Override public FileUpload duplicate() { DiskFileUpload upload = new DiskFileUpload( getName(), getFilename(), getContentType(), getContentTransferEncoding(), getCharset(), size); ByteBuf buf = content(); if (buf != null) { try { upload.setContent(buf.duplicate()); } catch (IOException e) { throw new ChannelException(e); } } return upload; }
@Test public void testFramesDecoded() { ByteBuf buf = Unpooled.buffer(); for (int i = 0; i < 9; i++) { buf.writeByte(i); } ByteBuf input = buf.duplicate(); EmbeddedChannel channel = new EmbeddedChannel(new FrameChunkDecoder(3)); Assert.assertTrue(channel.writeInbound(input.readBytes(2))); try { channel.writeInbound(input.readBytes(4)); Assert.fail(); } catch (TooLongFrameException e) { // expected } Assert.assertTrue(channel.writeInbound(input.readBytes(3))); Assert.assertTrue(channel.finish()); Assert.assertEquals(buf.readBytes(2), channel.readInbound()); Assert.assertEquals(buf.skipBytes(4).readBytes(3), channel.readInbound()); }
@Override public void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception { if (msg instanceof HttpRequest) { HttpRequest req = (HttpRequest) msg; if (is100ContinueExpected(req)) { ctx.write(new DefaultFullHttpResponse(HTTP_1_1, CONTINUE)); } boolean keepAlive = isKeepAlive(req); ByteBuf content = RESPONSE_BYTES.duplicate(); FullHttpResponse response = new DefaultFullHttpResponse(HTTP_1_1, OK, content); response.headers().set(CONTENT_TYPE, "text/html; charset=UTF-8"); response.headers().set(CONTENT_LENGTH, response.content().readableBytes()); if (!keepAlive) { ctx.write(response).addListener(ChannelFutureListener.CLOSE); } else { response.headers().set(CONNECTION, Values.KEEP_ALIVE); ctx.write(response); } } }
@Override protected void decode(ChannelHandlerContext ctx, HttpObject msg, MessageBuf<Object> out) throws Exception { FullHttpMessage currentMessage = this.currentMessage; if (msg instanceof HttpMessage) { assert currentMessage == null; HttpMessage m = (HttpMessage) msg; // Handle the 'Expect: 100-continue' header if necessary. // TODO: Respond with 413 Request Entity Too Large // and discard the traffic or close the connection. // No need to notify the upstream handlers - just log. // If decoding a response, just throw an exception. if (is100ContinueExpected(m)) { ctx.write(CONTINUE.duplicate()); } if (!m.getDecoderResult().isSuccess()) { removeTransferEncodingChunked(m); this.currentMessage = null; out.add(BufUtil.retain(m)); return; } if (msg instanceof HttpRequest) { HttpRequest header = (HttpRequest) msg; this.currentMessage = currentMessage = new DefaultFullHttpRequest( header.getProtocolVersion(), header.getMethod(), header.getUri(), Unpooled.compositeBuffer(maxCumulationBufferComponents)); } else if (msg instanceof HttpResponse) { HttpResponse header = (HttpResponse) msg; this.currentMessage = currentMessage = new DefaultFullHttpResponse( header.getProtocolVersion(), header.getStatus(), Unpooled.compositeBuffer(maxCumulationBufferComponents)); } else { throw new Error(); } currentMessage.headers().set(m.headers()); // A streamed message - initialize the cumulative buffer, and wait for incoming chunks. removeTransferEncodingChunked(currentMessage); } else if (msg instanceof HttpContent) { assert currentMessage != null; // Merge the received chunk into the content of the current message. HttpContent chunk = (HttpContent) msg; CompositeByteBuf content = (CompositeByteBuf) currentMessage.content(); if (content.readableBytes() > maxContentLength - chunk.content().readableBytes()) { // TODO: Respond with 413 Request Entity Too Large // and discard the traffic or close the connection. // No need to notify the upstream handlers - just log. // If decoding a response, just throw an exception. throw new TooLongFrameException( "HTTP content length exceeded " + maxContentLength + " bytes."); } // Append the content of the chunk if (chunk.content().isReadable()) { chunk.retain(); content.addComponent(chunk.content()); content.writerIndex(content.writerIndex() + chunk.content().readableBytes()); } final boolean last; if (!chunk.getDecoderResult().isSuccess()) { currentMessage.setDecoderResult(DecoderResult.failure(chunk.getDecoderResult().cause())); last = true; } else { last = chunk instanceof LastHttpContent; } if (last) { this.currentMessage = null; // Merge trailing headers into the message. if (chunk instanceof LastHttpContent) { LastHttpContent trailer = (LastHttpContent) chunk; currentMessage.headers().add(trailer.trailingHeaders()); } // Set the 'Content-Length' header. currentMessage .headers() .set(HttpHeaders.Names.CONTENT_LENGTH, String.valueOf(content.readableBytes())); // All done out.add(currentMessage); } } else { throw new Error(); } }
@Override public ByteBuf duplicate() { return buf.duplicate(); }
/** * Returns the Buffer as a Netty {@code ByteBuf}. * * <p>This method is meant for internal use only. */ public ByteBuf getByteBuf() { // Return a duplicate so the Buffer can be written multiple times. // See #648 return buffer.duplicate(); }
@Override public InputStream openStream() throws IOException { return new ByteBufInputStream(buf.duplicate()); }