public ResponseEvent(int rpcType, int coordinationId, ByteBuf pBody, ByteBuf dBody) { this.rpcType = rpcType; this.coordinationId = coordinationId; this.pBody = pBody; this.dBody = dBody; if (pBody != null) { pBody.retain(); } if (dBody != null) { dBody.retain(); } }
public void setBuffer(ByteBuf bufferHandle) { /* clear the existing buffer */ clear(); this.buffer = bufferHandle; buffer.retain(); }
/** * Adds a fragment to the block. * * @param fragment the fragment of the headers block to be added. * @param alloc allocator for new blocks if needed. * @param endOfHeaders flag indicating whether the current frame is the end of the headers. This * is used for an optimization for when the first fragment is the full block. In that case, * the buffer is used directly without copying. */ final void addFragment(ByteBuf fragment, ByteBufAllocator alloc, boolean endOfHeaders) throws Http2Exception { if (headerBlock == null) { if (fragment.readableBytes() > headersDecoder.configuration().maxHeaderSize()) { headerSizeExceeded(); } if (endOfHeaders) { // Optimization - don't bother copying, just use the buffer as-is. Need // to retain since we release when the header block is built. headerBlock = fragment.retain(); } else { headerBlock = alloc.buffer(fragment.readableBytes()); headerBlock.writeBytes(fragment); } return; } if (headersDecoder.configuration().maxHeaderSize() - fragment.readableBytes() < headerBlock.readableBytes()) { headerSizeExceeded(); } if (headerBlock.isWritable(fragment.readableBytes())) { // The buffer can hold the requested bytes, just write it directly. headerBlock.writeBytes(fragment); } else { // Allocate a new buffer that is big enough to hold the entire header block so far. ByteBuf buf = alloc.buffer(headerBlock.readableBytes() + fragment.readableBytes()); buf.writeBytes(headerBlock); buf.writeBytes(fragment); headerBlock.release(); headerBlock = buf; } }
RequestEvent(int coordinationId, C connection, int rpcType, ByteBuf pBody, ByteBuf dBody) { sender = new ResponseSenderImpl(); this.connection = connection; this.rpcType = rpcType; this.pBody = pBody; this.dBody = dBody; sender.set(connection, coordinationId); if (pBody != null) { pBody.retain(); } if (dBody != null) { dBody.retain(); } }
public ByteBuf getBuffer() { ByteBuf bufferHandle = this.buffer; /* Increment the ref count for this buffer */ bufferHandle.retain(); /* We are passing ownership of the buffer to the * caller. clear the buffer from within our selection vector */ clear(); return bufferHandle; }
@Override public ChannelFuture goAway( final ChannelHandlerContext ctx, final int lastStreamId, final long errorCode, final ByteBuf debugData, ChannelPromise promise) { try { final Http2Connection connection = connection(); if (connection.goAwaySent() && lastStreamId > connection.remote().lastStreamKnownByPeer()) { throw connectionError( PROTOCOL_ERROR, "Last stream identifier must not increase between " + "sending multiple GOAWAY frames (was '%d', is '%d').", connection.remote().lastStreamKnownByPeer(), lastStreamId); } connection.goAwaySent(lastStreamId, errorCode, debugData); // Need to retain before we write the buffer because if we do it after the refCnt could // already be 0 and // result in an IllegalRefCountException. debugData.retain(); ChannelFuture future = frameWriter().writeGoAway(ctx, lastStreamId, errorCode, debugData, promise); if (future.isDone()) { processGoAwayWriteResult(ctx, lastStreamId, errorCode, debugData, future); } else { future.addListener( new ChannelFutureListener() { @Override public void operationComplete(ChannelFuture future) throws Exception { processGoAwayWriteResult(ctx, lastStreamId, errorCode, debugData, future); } }); } return future; } catch ( Throwable cause) { // Make sure to catch Throwable because we are doing a retain() in this method. debugData.release(); return promise.setFailure(cause); } }
@Override protected void encode(ChannelHandlerContext ctx, ByteBuf byteBuf, List<Object> out) throws Exception { if (byteBuf.isReadable()) { int length = byteBuf.readableBytes(); String headerString = length + " "; ByteBuf header = ByteBufAllocator.DEFAULT.buffer(headerString.getBytes(Charset.forName("UTF8")).length); header.writeBytes(headerString.getBytes(Charset.forName("UTF8"))); Unpooled.buffer(); byteBuf.retain(); out.add(Unpooled.wrappedBuffer(header, byteBuf)); } }
@Override protected void notifyListenerOnDataRead( ChannelHandlerContext ctx, int streamId, ByteBuf data, int padding, boolean endOfStream, Http2FrameListener listener) throws Http2Exception { final Http2Stream stream = connection.stream(streamId); final EmbeddedChannel decoder = stream == null ? null : stream.decompressor(); if (decoder == null) { super.notifyListenerOnDataRead(ctx, streamId, data, padding, endOfStream, listener); } else { // call retain here as it will call release after its written to the channel decoder.writeInbound(data.retain()); ByteBuf buf = nextReadableBuf(decoder); if (buf == null) { if (endOfStream) { super.notifyListenerOnDataRead( ctx, streamId, Unpooled.EMPTY_BUFFER, padding, true, listener); } // END_STREAM is not set and the data could not be decoded yet. // The assumption has to be there will be more data frames to complete the decode. // We don't have enough information here to know if this is an error. } else { for (; ; ) { final ByteBuf nextBuf = nextReadableBuf(decoder); if (nextBuf == null) { super.notifyListenerOnDataRead(ctx, streamId, buf, padding, endOfStream, listener); break; } else { super.notifyListenerOnDataRead(ctx, streamId, buf, padding, false, listener); } buf = nextBuf; } } if (endOfStream) { cleanup(stream, decoder); } } }
public void send(@NotNull final FastCgiRequest fastCgiRequest, @NotNull ByteBuf content) { final ByteBuf notEmptyContent; if (content.isReadable()) { content.retain(); notEmptyContent = content; notEmptyContent.touch(); } else { notEmptyContent = null; } try { if (processHandler.has()) { fastCgiRequest.writeToServerChannel(notEmptyContent, processChannel); } else { processHandler .get() .done( new Consumer<OSProcessHandler>() { @Override public void consume(OSProcessHandler osProcessHandler) { fastCgiRequest.writeToServerChannel(notEmptyContent, processChannel); } }) .rejected( new Consumer<Throwable>() { @Override public void consume(Throwable error) { LOG.error(error); handleError(fastCgiRequest, notEmptyContent); } }); } } catch (Throwable e) { LOG.error(e); handleError(fastCgiRequest, notEmptyContent); } }
@Test public void test() throws Exception { // Preprocessor basically is split into two parts // Part 1 is just a direct copy // Part 2 negates all bytes before copying final AtomicReference<MessageProcessor> processor = new AtomicReference<>(); MessageProcessorDecoder processorDecoder = new MessageProcessorDecoder(null) { @Override protected MessageProcessor getProcessor() { return processor.get(); } }; // Set up a fake ChannelHandlerContext FakeChannelHandlerContext fake = ChannelHandlerContextFaker.setup(); AtomicReference<ByteBuf> ref = new AtomicReference<>(); fake.setReference(ref); LinkedList<byte[]> outputList = new LinkedList<byte[]>(); Random r = new Random(); // Get some random bytes for data byte[] input = new byte[LENGTH]; r.nextBytes(input); boolean breakOccured = false; int position = 0; for (int i = 0; i < input.length; ) { // Simulate real data read int burstSize = r.nextInt(512); // With a 1/10 chance of having an extra-large burst if (r.nextInt(10) == 0) { burstSize *= 10; } // Final burst needs to be clamped if (i + burstSize > input.length) { burstSize = input.length - i; } // And we can't negate in the middle of a burst if (i + burstSize > BREAK && !breakOccured) { burstSize = BREAK - i; } // Write info to a new ByteBuf final ByteBuf buf = Unpooled.buffer(burstSize); buf.retain(); buf.writeBytes(input, i, burstSize); i += burstSize; // Fake a read processorDecoder.channelRead(fake, buf); final ByteBuf returned = ref.get(); while (returned != null && true) { int packetSize = r.nextInt(128) + 1; if (r.nextInt(10) == 0) { packetSize *= 20; } if (packetSize > returned.readableBytes()) { packetSize = returned.readableBytes(); } if (position + packetSize > BREAK && !breakOccured) { packetSize = BREAK - position; } if (position + packetSize > LENGTH) { packetSize = LENGTH - position; } if (packetSize == 0) { break; } byte[] array = new byte[packetSize]; returned.readBytes(array); position += packetSize; if (position == BREAK) { processor.set(new NegatingProcessor(512)); breakOccured = true; } outputList.add(array); } } // Get the output data and combine into one array byte[] output = new byte[LENGTH]; int i = 0; for (byte[] array : outputList) { for (int j = 0; j < array.length; j++) { output[i++] = array[j]; } } for (i = 0; i < input.length; i++) { byte expected = i < BREAK ? input[i] : (byte) ~input[i]; if (output[i] != expected) { for (int j = Math.max(0, i - 10); j <= i + 10; j++) { System.out.println( j + ") " + Integer.toBinaryString(j < BREAK ? input[j] : (byte) ~input[j]) + " " + Integer.toBinaryString(output[j])); } } if (i < BREAK) { assertTrue( "Input/Output mismatch at position " + i + ". Expected " + input[i] + " but got " + output[i] + ". Break is: " + BREAK, output[i] == input[i]); } else { assertTrue( "Input/Output mismatch at position " + i + ", after the processor change. Expected " + (byte) ~input[i] + " but got " + output[i] + ". Break is: " + BREAK, output[i] == (byte) ~input[i]); } } }
public ReceivedResponse request(URI uri, Duration duration, Action<? super RequestSpec> action) throws Throwable { CountDownLatch latch = new CountDownLatch(1); AtomicReference<ExecResult<ReceivedResponse>> result = new AtomicReference<>(); try (ExecController execController = new DefaultExecController(2)) { execController .fork() .onComplete(e -> {}) .start( e -> { HttpClient.httpClient(UnpooledByteBufAllocator.DEFAULT, Integer.MAX_VALUE) .request(uri, action.prepend(s -> s.readTimeout(Duration.ofHours(1)))) .map( response -> { TypedData responseBody = response.getBody(); ByteBuf responseBodyBuffer = responseBody.getBuffer(); responseBodyBuffer = Unpooled.unreleasableBuffer(responseBodyBuffer.retain()); return new DefaultReceivedResponse( response.getStatus(), response.getHeaders(), new ByteBufBackedTypedData( responseBodyBuffer, responseBody.getContentType())); }) .connect( new Downstream<DefaultReceivedResponse>() { @Override public void success(DefaultReceivedResponse value) { result.set(ExecResult.of(Result.success(value))); latch.countDown(); } @Override public void error(Throwable throwable) { result.set(ExecResult.of(Result.error(throwable))); latch.countDown(); } @Override public void complete() { result.set(ExecResult.complete()); latch.countDown(); } }); }); try { if (!latch.await(duration.toNanos(), TimeUnit.NANOSECONDS)) { TemporalUnit unit = duration.getUnits().get(0); throw new IllegalStateException( "Request to " + uri + " took more than " + duration.get(unit) + " " + unit.toString() + " to complete"); } } catch (InterruptedException e) { throw Exceptions.uncheck(e); } return result.get().getValueOrThrow(); } }
@Override public ByteBuf retain(int var1) { return a.retain(var1); }
@Override public FullHttpMessage retain(int increment) { content.retain(increment); return this; }
@Override public FullHttpMessage retain() { content.retain(); return this; }
@Override public ByteBuf retain(int increment) { return buf.retain(increment); }
@Override public ByteBuf retain() { return buf.retain(); }
@Override public FullBinaryMemcacheResponse retain(int increment) { super.retain(increment); content.retain(increment); return this; }