/** * Puts {@code numBits} into the buffer with the value {@code value}. * * @param numBits The number of bits to put into the buffer. * @param value The value. * @throws IllegalStateException if the builder is not in bit access mode. * @throws IllegalArgumentException if the number of bits is not between 1 and 31 inclusive. */ public void putBits(int numBits, int value) { if (numBits <= 0 || numBits > 32) { throw new IllegalArgumentException("Number of bits must be between 1 and 31 inclusive"); } checkBitAccess(); int bytePos = bitIndex >> 3; int bitOffset = 8 - (bitIndex & 7); bitIndex += numBits; int requiredSpace = bytePos - buffer.writerIndex() + 1; requiredSpace += (numBits + 7) / 8; buffer.ensureWritable(requiredSpace); for (; numBits > bitOffset; bitOffset = 8) { int tmp = buffer.getByte(bytePos); tmp &= ~BITMASKS[bitOffset]; tmp |= (value >> (numBits - bitOffset)) & BITMASKS[bitOffset]; buffer.setByte(bytePos++, tmp); numBits -= bitOffset; } if (numBits == bitOffset) { int tmp = buffer.getByte(bytePos); tmp &= ~BITMASKS[bitOffset]; tmp |= value & BITMASKS[bitOffset]; buffer.setByte(bytePos, tmp); } else { int tmp = buffer.getByte(bytePos); tmp &= ~(BITMASKS[numBits] << (bitOffset - numBits)); tmp |= (value & BITMASKS[numBits]) << (bitOffset - numBits); buffer.setByte(bytePos, tmp); } }
private void ensureWritable(int pos, int len) { int ni = pos + len; int cap = buffer.capacity(); int over = ni - cap; if (over > 0) { buffer.writerIndex(cap); buffer.ensureWritable(over); } // We have to make sure that the writerindex is always positioned on the last bit of data set in // the buffer if (ni > buffer.writerIndex()) { buffer.writerIndex(ni); } }
private static SSLEngineResult unwrap(SSLEngine engine, ByteBuffer in, ByteBuf out) throws SSLException { int overflows = 0; for (; ; ) { ByteBuffer out0 = out.nioBuffer(out.writerIndex(), out.writableBytes()); SSLEngineResult result = engine.unwrap(in, out0); out.writerIndex(out.writerIndex() + result.bytesProduced()); switch (result.getStatus()) { case BUFFER_OVERFLOW: int max = engine.getSession().getApplicationBufferSize(); switch (overflows++) { case 0: out.ensureWritable(Math.min(max, in.remaining())); break; default: out.ensureWritable(max); } break; default: return result; } } }
private SSLEngineResult wrap(SSLEngine engine, ByteBuf in, ByteBuf out) throws SSLException { ByteBuffer in0 = in.nioBuffer(); for (; ; ) { ByteBuffer out0 = out.nioBuffer(out.writerIndex(), out.writableBytes()); SSLEngineResult result = engine.wrap(in0, out0); in.skipBytes(result.bytesConsumed()); out.writerIndex(out.writerIndex() + result.bytesProduced()); switch (result.getStatus()) { case BUFFER_OVERFLOW: out.ensureWritable(maxPacketBufferSize); break; default: return result; } } }
@Override protected void encode(ChannelHandlerContext ctx, Object msg, ByteBuf out) throws Exception { if (msg instanceof SpdyDataFrame) { SpdyDataFrame spdyDataFrame = (SpdyDataFrame) msg; ByteBuf data = spdyDataFrame.data(); byte flags = spdyDataFrame.isLast() ? SPDY_DATA_FLAG_FIN : 0; out.ensureWritable(SPDY_HEADER_SIZE + data.readableBytes()); out.writeInt(spdyDataFrame.getStreamId() & 0x7FFFFFFF); out.writeByte(flags); out.writeMedium(data.readableBytes()); out.writeBytes(data, data.readerIndex(), data.readableBytes()); } else if (msg instanceof SpdySynStreamFrame) { SpdySynStreamFrame spdySynStreamFrame = (SpdySynStreamFrame) msg; ByteBuf data = compressHeaderBlock(encodeHeaderBlock(version, spdySynStreamFrame)); byte flags = spdySynStreamFrame.isLast() ? SPDY_FLAG_FIN : 0; if (spdySynStreamFrame.isUnidirectional()) { flags |= SPDY_FLAG_UNIDIRECTIONAL; } int headerBlockLength = data.readableBytes(); int length; if (version < 3) { length = headerBlockLength == 0 ? 12 : 10 + headerBlockLength; } else { length = 10 + headerBlockLength; } out.ensureWritable(SPDY_HEADER_SIZE + length); out.writeShort(version | 0x8000); out.writeShort(SPDY_SYN_STREAM_FRAME); out.writeByte(flags); out.writeMedium(length); out.writeInt(spdySynStreamFrame.getStreamId()); out.writeInt(spdySynStreamFrame.getAssociatedToStreamId()); if (version < 3) { // Restrict priorities for SPDY/2 to between 0 and 3 byte priority = spdySynStreamFrame.getPriority(); if (priority > 3) { priority = 3; } out.writeShort((priority & 0xFF) << 14); } else { out.writeShort((spdySynStreamFrame.getPriority() & 0xFF) << 13); } if (version < 3 && data.readableBytes() == 0) { out.writeShort(0); } out.writeBytes(data, data.readerIndex(), headerBlockLength); } else if (msg instanceof SpdySynReplyFrame) { SpdySynReplyFrame spdySynReplyFrame = (SpdySynReplyFrame) msg; ByteBuf data = compressHeaderBlock(encodeHeaderBlock(version, spdySynReplyFrame)); byte flags = spdySynReplyFrame.isLast() ? SPDY_FLAG_FIN : 0; int headerBlockLength = data.readableBytes(); int length; if (version < 3) { length = headerBlockLength == 0 ? 8 : 6 + headerBlockLength; } else { length = 4 + headerBlockLength; } out.ensureWritable(SPDY_HEADER_SIZE + length); out.writeShort(version | 0x8000); out.writeShort(SPDY_SYN_REPLY_FRAME); out.writeByte(flags); out.writeMedium(length); out.writeInt(spdySynReplyFrame.getStreamId()); if (version < 3) { if (headerBlockLength == 0) { out.writeInt(0); } else { out.writeShort(0); } } out.writeBytes(data, data.readerIndex(), headerBlockLength); } else if (msg instanceof SpdyRstStreamFrame) { SpdyRstStreamFrame spdyRstStreamFrame = (SpdyRstStreamFrame) msg; out.ensureWritable(SPDY_HEADER_SIZE + 8); out.writeShort(version | 0x8000); out.writeShort(SPDY_RST_STREAM_FRAME); out.writeInt(8); out.writeInt(spdyRstStreamFrame.getStreamId()); out.writeInt(spdyRstStreamFrame.getStatus().getCode()); } else if (msg instanceof SpdySettingsFrame) { SpdySettingsFrame spdySettingsFrame = (SpdySettingsFrame) msg; byte flags = spdySettingsFrame.clearPreviouslyPersistedSettings() ? SPDY_SETTINGS_CLEAR : 0; Set<Integer> IDs = spdySettingsFrame.getIds(); int numEntries = IDs.size(); int length = 4 + numEntries * 8; out.ensureWritable(SPDY_HEADER_SIZE + length); out.writeShort(version | 0x8000); out.writeShort(SPDY_SETTINGS_FRAME); out.writeByte(flags); out.writeMedium(length); out.writeInt(numEntries); for (Integer ID : IDs) { int id = ID.intValue(); byte ID_flags = 0; if (spdySettingsFrame.isPersistValue(id)) { ID_flags |= SPDY_SETTINGS_PERSIST_VALUE; } if (spdySettingsFrame.isPersisted(id)) { ID_flags |= SPDY_SETTINGS_PERSISTED; } if (version < 3) { // Chromium Issue 79156 // SPDY setting ids are not written in network byte order // Write id assuming the architecture is little endian out.writeByte(id & 0xFF); out.writeByte(id >> 8 & 0xFF); out.writeByte(id >> 16 & 0xFF); out.writeByte(ID_flags); } else { out.writeByte(ID_flags); out.writeMedium(id); } out.writeInt(spdySettingsFrame.getValue(id)); } } else if (msg instanceof SpdyNoOpFrame) { out.ensureWritable(SPDY_HEADER_SIZE); out.writeShort(version | 0x8000); out.writeShort(SPDY_NOOP_FRAME); out.writeInt(0); } else if (msg instanceof SpdyPingFrame) { SpdyPingFrame spdyPingFrame = (SpdyPingFrame) msg; out.ensureWritable(SPDY_HEADER_SIZE + 4); out.writeShort(version | 0x8000); out.writeShort(SPDY_PING_FRAME); out.writeInt(4); out.writeInt(spdyPingFrame.getId()); } else if (msg instanceof SpdyGoAwayFrame) { SpdyGoAwayFrame spdyGoAwayFrame = (SpdyGoAwayFrame) msg; int length = version < 3 ? 4 : 8; out.ensureWritable(SPDY_HEADER_SIZE + length); out.writeShort(version | 0x8000); out.writeShort(SPDY_GOAWAY_FRAME); out.writeInt(length); out.writeInt(spdyGoAwayFrame.getLastGoodStreamId()); if (version >= 3) { out.writeInt(spdyGoAwayFrame.getStatus().getCode()); } } else if (msg instanceof SpdyHeadersFrame) { SpdyHeadersFrame spdyHeadersFrame = (SpdyHeadersFrame) msg; ByteBuf data = compressHeaderBlock(encodeHeaderBlock(version, spdyHeadersFrame)); byte flags = spdyHeadersFrame.isLast() ? SPDY_FLAG_FIN : 0; int headerBlockLength = data.readableBytes(); int length; if (version < 3) { length = headerBlockLength == 0 ? 4 : 6 + headerBlockLength; } else { length = 4 + headerBlockLength; } out.ensureWritable(SPDY_HEADER_SIZE + length); out.writeShort(version | 0x8000); out.writeShort(SPDY_HEADERS_FRAME); out.writeByte(flags); out.writeMedium(length); out.writeInt(spdyHeadersFrame.getStreamId()); if (version < 3 && headerBlockLength != 0) { out.writeShort(0); } out.writeBytes(data, data.readerIndex(), headerBlockLength); } else if (msg instanceof SpdyWindowUpdateFrame) { SpdyWindowUpdateFrame spdyWindowUpdateFrame = (SpdyWindowUpdateFrame) msg; out.ensureWritable(SPDY_HEADER_SIZE + 8); out.writeShort(version | 0x8000); out.writeShort(SPDY_WINDOW_UPDATE_FRAME); out.writeInt(8); out.writeInt(spdyWindowUpdateFrame.getStreamId()); out.writeInt(spdyWindowUpdateFrame.getDeltaWindowSize()); } else { throw new UnsupportedMessageTypeException(msg); } }
@Override protected void doRead() { if (checkInputShutdown()) { return; } final ChannelPipeline pipeline = pipeline(); // TODO: calculate size as in 3.x ByteBuf byteBuf = alloc().buffer(); boolean closed = false; boolean read = false; boolean firedInboundBufferSuspeneded = false; try { for (; ; ) { int localReadAmount = doReadBytes(byteBuf); if (localReadAmount > 0) { read = true; } else if (localReadAmount < 0) { closed = true; } final int available = available(); if (available <= 0) { break; } if (!byteBuf.isWritable()) { final int capacity = byteBuf.capacity(); final int maxCapacity = byteBuf.maxCapacity(); if (capacity == maxCapacity) { if (read) { read = false; pipeline.fireMessageReceived(byteBuf); byteBuf = alloc().buffer(); } } else { final int writerIndex = byteBuf.writerIndex(); if (writerIndex + available > maxCapacity) { byteBuf.capacity(maxCapacity); } else { byteBuf.ensureWritable(available); } } } if (!config().isAutoRead()) { // stop reading until next Channel.read() call // See https://github.com/netty/netty/issues/1363 break; } } } catch (Throwable t) { if (read) { read = false; pipeline.fireMessageReceived(byteBuf); } if (t instanceof IOException) { closed = true; pipeline.fireExceptionCaught(t); } else { firedInboundBufferSuspeneded = true; pipeline.fireChannelReadSuspended(); pipeline.fireExceptionCaught(t); unsafe().close(voidPromise()); } } finally { if (read) { pipeline.fireMessageReceived(byteBuf); } else { // nothing read into the buffer so release it byteBuf.release(); } if (closed) { inputShutdown = true; if (isOpen()) { if (Boolean.TRUE.equals(config().getOption(ChannelOption.ALLOW_HALF_CLOSURE))) { pipeline.fireUserEventTriggered(ChannelInputShutdownEvent.INSTANCE); } else { unsafe().close(unsafe().voidPromise()); } } } else if (!firedInboundBufferSuspeneded) { pipeline.fireChannelReadSuspended(); } } }
private SSLEngineResult wrap(ByteBufAllocator alloc, SSLEngine engine, ByteBuf in, ByteBuf out) throws SSLException { ByteBuf newDirectIn = null; try { int readerIndex = in.readerIndex(); int readableBytes = in.readableBytes(); // We will call SslEngine.wrap(ByteBuffer[], ByteBuffer) to allow efficient handling of // CompositeByteBuf without force an extra memory copy when CompositeByteBuffer.nioBuffer() is // called. final ByteBuffer[] in0; if (in.isDirect() || !wantsDirectBuffer) { // As CompositeByteBuf.nioBufferCount() can be expensive (as it needs to check all composed // ByteBuf // to calculate the count) we will just assume a CompositeByteBuf contains more then 1 // ByteBuf. // The worst that can happen is that we allocate an extra ByteBuffer[] in // CompositeByteBuf.nioBuffers() // which is better then walking the composed ByteBuf in most cases. if (!(in instanceof CompositeByteBuf) && in.nioBufferCount() == 1) { in0 = singleBuffer; // We know its only backed by 1 ByteBuffer so use internalNioBuffer to keep object // allocation // to a minimum. in0[0] = in.internalNioBuffer(readerIndex, readableBytes); } else { in0 = in.nioBuffers(); } } else { // We could even go further here and check if its a CompositeByteBuf and if so try to // decompose it and // only replace the ByteBuffer that are not direct. At the moment we just will replace the // whole // CompositeByteBuf to keep the complexity to a minimum newDirectIn = alloc.directBuffer(readableBytes); newDirectIn.writeBytes(in, readerIndex, readableBytes); in0 = singleBuffer; in0[0] = newDirectIn.internalNioBuffer(0, readableBytes); } for (; ; ) { ByteBuffer out0 = out.nioBuffer(out.writerIndex(), out.writableBytes()); SSLEngineResult result = engine.wrap(in0, out0); in.skipBytes(result.bytesConsumed()); out.writerIndex(out.writerIndex() + result.bytesProduced()); switch (result.getStatus()) { case BUFFER_OVERFLOW: out.ensureWritable(maxPacketBufferSize); break; default: return result; } } } finally { // Null out to allow GC of ByteBuffer singleBuffer[0] = null; if (newDirectIn != null) { newDirectIn.release(); } } }
@Override public int ensureWritable(int minWritableBytes, boolean force) { return buf.ensureWritable(minWritableBytes, force); }
@Override public ByteBuf ensureWritable(int minWritableBytes) { return buf.ensureWritable(minWritableBytes); }
@Override public int ensureWritable(int var1, boolean var2) { return a.ensureWritable(var1, var2); }
@Override public ByteBuf ensureWritable(int var1) { return a.ensureWritable(var1); }