code: private boolean decodeBuffer(ByteBuf in, ChannelHandlerContext ctx) throws IOException {
  
  		DecoderState decoderState;
  		while ((decoderState = decodeEnvelope(in)) != DecoderState.PENDING) {
  			if (decoderState == DecoderState.COMPLETE) {
  				ctx.fireChannelRead(this.currentEnvelope);
  				this.currentEnvelope = null;
  			}
  			else if (decoderState == DecoderState.NO_BUFFER_AVAILABLE) {
  				switch (this.currentBufferProvider.registerBufferAvailabilityListener(this)) {
  					case SUCCEEDED_REGISTERED:
  						if (ctx.channel().config().isAutoRead()) {
  							ctx.channel().config().setAutoRead(false);
  
  							if (LOG.isDebugEnabled()) {
  								LOG.debug(String.format("Set channel %s auto read to false.", ctx.channel()));
  							}
  						}
  
  						this.stagedBuffer = in;
  						this.stagedBuffer.retain();
  						return false;
  
  					case FAILED_BUFFER_AVAILABLE:
  						continue;
  
  					case FAILED_BUFFER_POOL_DESTROYED:
  						this.bytesToSkip = skipBytes(in, this.currentBufferRequestSize);
  
  						this.currentBufferRequestSize = 0;
  						this.currentEventsBuffer = null;
  						this.currentEnvelope = null;
  				}
  			}
  		}
  
  		if (in.isReadable()) {
  			throw new IllegalStateException("Every buffer should have been fully" +
  					"consumed after *successfully* decoding it (if it was not successful, " +
  					"the buffer will be staged for later consumption).");
  		}
  
  		in.release();
  		return true;
  	}
docs: Decodes all Envelopes contained in a Netty ByteBuf and forwards them in the pipeline.
  Returns true and releases the buffer, if it was fully consumed. Otherwise, returns false and retains the buffer.
  </p>
  In case of no buffer availability (returns false), a buffer availability listener is registered and the input
  buffer is staged for later consumption.
  
  @return <code>true</code>, if buffer fully consumed, <code>false</code> otherwise
  @throws IOException