diff -Nru netty-4.0.33/all/pom.xml netty-4.0.34/all/pom.xml
--- netty-4.0.33/all/pom.xml 2015-11-03 13:18:17.000000000 +0000
+++ netty-4.0.34/all/pom.xml 2016-01-29 08:23:46.000000000 +0000
@@ -20,7 +20,7 @@
io.nettynetty-parent
- 4.0.33.Final
+ 4.0.34.Finalnetty-all
diff -Nru netty-4.0.33/buffer/pom.xml netty-4.0.34/buffer/pom.xml
--- netty-4.0.33/buffer/pom.xml 2015-11-03 13:18:17.000000000 +0000
+++ netty-4.0.34/buffer/pom.xml 2016-01-29 08:23:46.000000000 +0000
@@ -20,7 +20,7 @@
io.nettynetty-parent
- 4.0.33.Final
+ 4.0.34.Finalnetty-buffer
diff -Nru netty-4.0.33/buffer/src/main/java/io/netty/buffer/AbstractByteBufAllocator.java netty-4.0.34/buffer/src/main/java/io/netty/buffer/AbstractByteBufAllocator.java
--- netty-4.0.33/buffer/src/main/java/io/netty/buffer/AbstractByteBufAllocator.java 2015-11-03 13:18:17.000000000 +0000
+++ netty-4.0.34/buffer/src/main/java/io/netty/buffer/AbstractByteBufAllocator.java 2016-01-29 08:23:46.000000000 +0000
@@ -26,7 +26,7 @@
*/
public abstract class AbstractByteBufAllocator implements ByteBufAllocator {
private static final int DEFAULT_INITIAL_CAPACITY = 256;
- private static final int DEFAULT_MAX_COMPONENTS = 16;
+ static final int DEFAULT_MAX_COMPONENTS = 16;
protected static ByteBuf toLeakAwareBuffer(ByteBuf buf) {
ResourceLeak leak;
@@ -48,6 +48,28 @@
return buf;
}
+ protected static CompositeByteBuf toLeakAwareBuffer(CompositeByteBuf buf) {
+ ResourceLeak leak;
+ switch (ResourceLeakDetector.getLevel()) {
+ case SIMPLE:
+ leak = AbstractByteBuf.leakDetector.open(buf);
+ if (leak != null) {
+ buf = new SimpleLeakAwareCompositeByteBuf(buf, leak);
+ }
+ break;
+ case ADVANCED:
+ case PARANOID:
+ leak = AbstractByteBuf.leakDetector.open(buf);
+ if (leak != null) {
+ buf = new AdvancedLeakAwareCompositeByteBuf(buf, leak);
+ }
+ break;
+ default:
+ break;
+ }
+ return buf;
+ }
+
private final boolean directByDefault;
private final ByteBuf emptyBuf;
@@ -178,7 +200,7 @@
@Override
public CompositeByteBuf compositeHeapBuffer(int maxNumComponents) {
- return new CompositeByteBuf(this, false, maxNumComponents);
+ return toLeakAwareBuffer(new CompositeByteBuf(this, false, maxNumComponents));
}
@Override
@@ -188,7 +210,7 @@
@Override
public CompositeByteBuf compositeDirectBuffer(int maxNumComponents) {
- return new CompositeByteBuf(this, true, maxNumComponents);
+ return toLeakAwareBuffer(new CompositeByteBuf(this, true, maxNumComponents));
}
private static void validate(int initialCapacity, int maxCapacity) {
diff -Nru netty-4.0.33/buffer/src/main/java/io/netty/buffer/AbstractReferenceCountedByteBuf.java netty-4.0.34/buffer/src/main/java/io/netty/buffer/AbstractReferenceCountedByteBuf.java
--- netty-4.0.33/buffer/src/main/java/io/netty/buffer/AbstractReferenceCountedByteBuf.java 2015-11-03 13:18:17.000000000 +0000
+++ netty-4.0.34/buffer/src/main/java/io/netty/buffer/AbstractReferenceCountedByteBuf.java 2016-01-29 08:23:46.000000000 +0000
@@ -44,7 +44,7 @@
}
@Override
- public final int refCnt() {
+ public int refCnt() {
return refCnt;
}
@@ -94,7 +94,7 @@
}
@Override
- public final boolean release() {
+ public boolean release() {
for (;;) {
int refCnt = this.refCnt;
if (refCnt == 0) {
@@ -112,7 +112,7 @@
}
@Override
- public final boolean release(int decrement) {
+ public boolean release(int decrement) {
if (decrement <= 0) {
throw new IllegalArgumentException("decrement: " + decrement + " (expected: > 0)");
}
diff -Nru netty-4.0.33/buffer/src/main/java/io/netty/buffer/AdvancedLeakAwareByteBuf.java netty-4.0.34/buffer/src/main/java/io/netty/buffer/AdvancedLeakAwareByteBuf.java
--- netty-4.0.33/buffer/src/main/java/io/netty/buffer/AdvancedLeakAwareByteBuf.java 2015-11-03 13:18:17.000000000 +0000
+++ netty-4.0.34/buffer/src/main/java/io/netty/buffer/AdvancedLeakAwareByteBuf.java 2016-01-29 08:23:46.000000000 +0000
@@ -74,7 +74,7 @@
return deallocated;
}
- private void recordLeakNonRefCountingOperation() {
+ static void recordLeakNonRefCountingOperation(ResourceLeak leak) {
if (!ACQUIRE_AND_RELEASE_ONLY) {
leak.record();
}
@@ -82,7 +82,7 @@
@Override
public ByteBuf order(ByteOrder endianness) {
- recordLeakNonRefCountingOperation();
+ recordLeakNonRefCountingOperation(leak);
if (order() == endianness) {
return this;
} else {
@@ -92,637 +92,637 @@
@Override
public ByteBuf slice() {
- recordLeakNonRefCountingOperation();
+ recordLeakNonRefCountingOperation(leak);
return new AdvancedLeakAwareByteBuf(super.slice(), leak);
}
@Override
public ByteBuf slice(int index, int length) {
- recordLeakNonRefCountingOperation();
+ recordLeakNonRefCountingOperation(leak);
return new AdvancedLeakAwareByteBuf(super.slice(index, length), leak);
}
@Override
public ByteBuf duplicate() {
- recordLeakNonRefCountingOperation();
+ recordLeakNonRefCountingOperation(leak);
return new AdvancedLeakAwareByteBuf(super.duplicate(), leak);
}
@Override
public ByteBuf readSlice(int length) {
- recordLeakNonRefCountingOperation();
+ recordLeakNonRefCountingOperation(leak);
return new AdvancedLeakAwareByteBuf(super.readSlice(length), leak);
}
@Override
public ByteBuf discardReadBytes() {
- recordLeakNonRefCountingOperation();
+ recordLeakNonRefCountingOperation(leak);
return super.discardReadBytes();
}
@Override
public ByteBuf discardSomeReadBytes() {
- recordLeakNonRefCountingOperation();
+ recordLeakNonRefCountingOperation(leak);
return super.discardSomeReadBytes();
}
@Override
public ByteBuf ensureWritable(int minWritableBytes) {
- recordLeakNonRefCountingOperation();
+ recordLeakNonRefCountingOperation(leak);
return super.ensureWritable(minWritableBytes);
}
@Override
public int ensureWritable(int minWritableBytes, boolean force) {
- recordLeakNonRefCountingOperation();
+ recordLeakNonRefCountingOperation(leak);
return super.ensureWritable(minWritableBytes, force);
}
@Override
public boolean getBoolean(int index) {
- recordLeakNonRefCountingOperation();
+ recordLeakNonRefCountingOperation(leak);
return super.getBoolean(index);
}
@Override
public byte getByte(int index) {
- recordLeakNonRefCountingOperation();
+ recordLeakNonRefCountingOperation(leak);
return super.getByte(index);
}
@Override
public short getUnsignedByte(int index) {
- recordLeakNonRefCountingOperation();
+ recordLeakNonRefCountingOperation(leak);
return super.getUnsignedByte(index);
}
@Override
public short getShort(int index) {
- recordLeakNonRefCountingOperation();
+ recordLeakNonRefCountingOperation(leak);
return super.getShort(index);
}
@Override
public int getUnsignedShort(int index) {
- recordLeakNonRefCountingOperation();
+ recordLeakNonRefCountingOperation(leak);
return super.getUnsignedShort(index);
}
@Override
public int getMedium(int index) {
- recordLeakNonRefCountingOperation();
+ recordLeakNonRefCountingOperation(leak);
return super.getMedium(index);
}
@Override
public int getUnsignedMedium(int index) {
- recordLeakNonRefCountingOperation();
+ recordLeakNonRefCountingOperation(leak);
return super.getUnsignedMedium(index);
}
@Override
public int getInt(int index) {
- recordLeakNonRefCountingOperation();
+ recordLeakNonRefCountingOperation(leak);
return super.getInt(index);
}
@Override
public long getUnsignedInt(int index) {
- recordLeakNonRefCountingOperation();
+ recordLeakNonRefCountingOperation(leak);
return super.getUnsignedInt(index);
}
@Override
public long getLong(int index) {
- recordLeakNonRefCountingOperation();
+ recordLeakNonRefCountingOperation(leak);
return super.getLong(index);
}
@Override
public char getChar(int index) {
- recordLeakNonRefCountingOperation();
+ recordLeakNonRefCountingOperation(leak);
return super.getChar(index);
}
@Override
public float getFloat(int index) {
- recordLeakNonRefCountingOperation();
+ recordLeakNonRefCountingOperation(leak);
return super.getFloat(index);
}
@Override
public double getDouble(int index) {
- recordLeakNonRefCountingOperation();
+ recordLeakNonRefCountingOperation(leak);
return super.getDouble(index);
}
@Override
public ByteBuf getBytes(int index, ByteBuf dst) {
- recordLeakNonRefCountingOperation();
+ recordLeakNonRefCountingOperation(leak);
return super.getBytes(index, dst);
}
@Override
public ByteBuf getBytes(int index, ByteBuf dst, int length) {
- recordLeakNonRefCountingOperation();
+ recordLeakNonRefCountingOperation(leak);
return super.getBytes(index, dst, length);
}
@Override
public ByteBuf getBytes(int index, ByteBuf dst, int dstIndex, int length) {
- recordLeakNonRefCountingOperation();
+ recordLeakNonRefCountingOperation(leak);
return super.getBytes(index, dst, dstIndex, length);
}
@Override
public ByteBuf getBytes(int index, byte[] dst) {
- recordLeakNonRefCountingOperation();
+ recordLeakNonRefCountingOperation(leak);
return super.getBytes(index, dst);
}
@Override
public ByteBuf getBytes(int index, byte[] dst, int dstIndex, int length) {
- recordLeakNonRefCountingOperation();
+ recordLeakNonRefCountingOperation(leak);
return super.getBytes(index, dst, dstIndex, length);
}
@Override
public ByteBuf getBytes(int index, ByteBuffer dst) {
- recordLeakNonRefCountingOperation();
+ recordLeakNonRefCountingOperation(leak);
return super.getBytes(index, dst);
}
@Override
public ByteBuf getBytes(int index, OutputStream out, int length) throws IOException {
- recordLeakNonRefCountingOperation();
+ recordLeakNonRefCountingOperation(leak);
return super.getBytes(index, out, length);
}
@Override
public int getBytes(int index, GatheringByteChannel out, int length) throws IOException {
- recordLeakNonRefCountingOperation();
+ recordLeakNonRefCountingOperation(leak);
return super.getBytes(index, out, length);
}
@Override
public ByteBuf setBoolean(int index, boolean value) {
- recordLeakNonRefCountingOperation();
+ recordLeakNonRefCountingOperation(leak);
return super.setBoolean(index, value);
}
@Override
public ByteBuf setByte(int index, int value) {
- recordLeakNonRefCountingOperation();
+ recordLeakNonRefCountingOperation(leak);
return super.setByte(index, value);
}
@Override
public ByteBuf setShort(int index, int value) {
- recordLeakNonRefCountingOperation();
+ recordLeakNonRefCountingOperation(leak);
return super.setShort(index, value);
}
@Override
public ByteBuf setMedium(int index, int value) {
- recordLeakNonRefCountingOperation();
+ recordLeakNonRefCountingOperation(leak);
return super.setMedium(index, value);
}
@Override
public ByteBuf setInt(int index, int value) {
- recordLeakNonRefCountingOperation();
+ recordLeakNonRefCountingOperation(leak);
return super.setInt(index, value);
}
@Override
public ByteBuf setLong(int index, long value) {
- recordLeakNonRefCountingOperation();
+ recordLeakNonRefCountingOperation(leak);
return super.setLong(index, value);
}
@Override
public ByteBuf setChar(int index, int value) {
- recordLeakNonRefCountingOperation();
+ recordLeakNonRefCountingOperation(leak);
return super.setChar(index, value);
}
@Override
public ByteBuf setFloat(int index, float value) {
- recordLeakNonRefCountingOperation();
+ recordLeakNonRefCountingOperation(leak);
return super.setFloat(index, value);
}
@Override
public ByteBuf setDouble(int index, double value) {
- recordLeakNonRefCountingOperation();
+ recordLeakNonRefCountingOperation(leak);
return super.setDouble(index, value);
}
@Override
public ByteBuf setBytes(int index, ByteBuf src) {
- recordLeakNonRefCountingOperation();
+ recordLeakNonRefCountingOperation(leak);
return super.setBytes(index, src);
}
@Override
public ByteBuf setBytes(int index, ByteBuf src, int length) {
- recordLeakNonRefCountingOperation();
+ recordLeakNonRefCountingOperation(leak);
return super.setBytes(index, src, length);
}
@Override
public ByteBuf setBytes(int index, ByteBuf src, int srcIndex, int length) {
- recordLeakNonRefCountingOperation();
+ recordLeakNonRefCountingOperation(leak);
return super.setBytes(index, src, srcIndex, length);
}
@Override
public ByteBuf setBytes(int index, byte[] src) {
- recordLeakNonRefCountingOperation();
+ recordLeakNonRefCountingOperation(leak);
return super.setBytes(index, src);
}
@Override
public ByteBuf setBytes(int index, byte[] src, int srcIndex, int length) {
- recordLeakNonRefCountingOperation();
+ recordLeakNonRefCountingOperation(leak);
return super.setBytes(index, src, srcIndex, length);
}
@Override
public ByteBuf setBytes(int index, ByteBuffer src) {
- recordLeakNonRefCountingOperation();
+ recordLeakNonRefCountingOperation(leak);
return super.setBytes(index, src);
}
@Override
public int setBytes(int index, InputStream in, int length) throws IOException {
- recordLeakNonRefCountingOperation();
+ recordLeakNonRefCountingOperation(leak);
return super.setBytes(index, in, length);
}
@Override
public int setBytes(int index, ScatteringByteChannel in, int length) throws IOException {
- recordLeakNonRefCountingOperation();
+ recordLeakNonRefCountingOperation(leak);
return super.setBytes(index, in, length);
}
@Override
public ByteBuf setZero(int index, int length) {
- recordLeakNonRefCountingOperation();
+ recordLeakNonRefCountingOperation(leak);
return super.setZero(index, length);
}
@Override
public boolean readBoolean() {
- recordLeakNonRefCountingOperation();
+ recordLeakNonRefCountingOperation(leak);
return super.readBoolean();
}
@Override
public byte readByte() {
- recordLeakNonRefCountingOperation();
+ recordLeakNonRefCountingOperation(leak);
return super.readByte();
}
@Override
public short readUnsignedByte() {
- recordLeakNonRefCountingOperation();
+ recordLeakNonRefCountingOperation(leak);
return super.readUnsignedByte();
}
@Override
public short readShort() {
- recordLeakNonRefCountingOperation();
+ recordLeakNonRefCountingOperation(leak);
return super.readShort();
}
@Override
public int readUnsignedShort() {
- recordLeakNonRefCountingOperation();
+ recordLeakNonRefCountingOperation(leak);
return super.readUnsignedShort();
}
@Override
public int readMedium() {
- recordLeakNonRefCountingOperation();
+ recordLeakNonRefCountingOperation(leak);
return super.readMedium();
}
@Override
public int readUnsignedMedium() {
- recordLeakNonRefCountingOperation();
+ recordLeakNonRefCountingOperation(leak);
return super.readUnsignedMedium();
}
@Override
public int readInt() {
- recordLeakNonRefCountingOperation();
+ recordLeakNonRefCountingOperation(leak);
return super.readInt();
}
@Override
public long readUnsignedInt() {
- recordLeakNonRefCountingOperation();
+ recordLeakNonRefCountingOperation(leak);
return super.readUnsignedInt();
}
@Override
public long readLong() {
- recordLeakNonRefCountingOperation();
+ recordLeakNonRefCountingOperation(leak);
return super.readLong();
}
@Override
public char readChar() {
- recordLeakNonRefCountingOperation();
+ recordLeakNonRefCountingOperation(leak);
return super.readChar();
}
@Override
public float readFloat() {
- recordLeakNonRefCountingOperation();
+ recordLeakNonRefCountingOperation(leak);
return super.readFloat();
}
@Override
public double readDouble() {
- recordLeakNonRefCountingOperation();
+ recordLeakNonRefCountingOperation(leak);
return super.readDouble();
}
@Override
public ByteBuf readBytes(int length) {
- recordLeakNonRefCountingOperation();
+ recordLeakNonRefCountingOperation(leak);
return super.readBytes(length);
}
@Override
public ByteBuf readBytes(ByteBuf dst) {
- recordLeakNonRefCountingOperation();
+ recordLeakNonRefCountingOperation(leak);
return super.readBytes(dst);
}
@Override
public ByteBuf readBytes(ByteBuf dst, int length) {
- recordLeakNonRefCountingOperation();
+ recordLeakNonRefCountingOperation(leak);
return super.readBytes(dst, length);
}
@Override
public ByteBuf readBytes(ByteBuf dst, int dstIndex, int length) {
- recordLeakNonRefCountingOperation();
+ recordLeakNonRefCountingOperation(leak);
return super.readBytes(dst, dstIndex, length);
}
@Override
public ByteBuf readBytes(byte[] dst) {
- recordLeakNonRefCountingOperation();
+ recordLeakNonRefCountingOperation(leak);
return super.readBytes(dst);
}
@Override
public ByteBuf readBytes(byte[] dst, int dstIndex, int length) {
- recordLeakNonRefCountingOperation();
+ recordLeakNonRefCountingOperation(leak);
return super.readBytes(dst, dstIndex, length);
}
@Override
public ByteBuf readBytes(ByteBuffer dst) {
- recordLeakNonRefCountingOperation();
+ recordLeakNonRefCountingOperation(leak);
return super.readBytes(dst);
}
@Override
public ByteBuf readBytes(OutputStream out, int length) throws IOException {
- recordLeakNonRefCountingOperation();
+ recordLeakNonRefCountingOperation(leak);
return super.readBytes(out, length);
}
@Override
public int readBytes(GatheringByteChannel out, int length) throws IOException {
- recordLeakNonRefCountingOperation();
+ recordLeakNonRefCountingOperation(leak);
return super.readBytes(out, length);
}
@Override
public ByteBuf skipBytes(int length) {
- recordLeakNonRefCountingOperation();
+ recordLeakNonRefCountingOperation(leak);
return super.skipBytes(length);
}
@Override
public ByteBuf writeBoolean(boolean value) {
- recordLeakNonRefCountingOperation();
+ recordLeakNonRefCountingOperation(leak);
return super.writeBoolean(value);
}
@Override
public ByteBuf writeByte(int value) {
- recordLeakNonRefCountingOperation();
+ recordLeakNonRefCountingOperation(leak);
return super.writeByte(value);
}
@Override
public ByteBuf writeShort(int value) {
- recordLeakNonRefCountingOperation();
+ recordLeakNonRefCountingOperation(leak);
return super.writeShort(value);
}
@Override
public ByteBuf writeMedium(int value) {
- recordLeakNonRefCountingOperation();
+ recordLeakNonRefCountingOperation(leak);
return super.writeMedium(value);
}
@Override
public ByteBuf writeInt(int value) {
- recordLeakNonRefCountingOperation();
+ recordLeakNonRefCountingOperation(leak);
return super.writeInt(value);
}
@Override
public ByteBuf writeLong(long value) {
- recordLeakNonRefCountingOperation();
+ recordLeakNonRefCountingOperation(leak);
return super.writeLong(value);
}
@Override
public ByteBuf writeChar(int value) {
- recordLeakNonRefCountingOperation();
+ recordLeakNonRefCountingOperation(leak);
return super.writeChar(value);
}
@Override
public ByteBuf writeFloat(float value) {
- recordLeakNonRefCountingOperation();
+ recordLeakNonRefCountingOperation(leak);
return super.writeFloat(value);
}
@Override
public ByteBuf writeDouble(double value) {
- recordLeakNonRefCountingOperation();
+ recordLeakNonRefCountingOperation(leak);
return super.writeDouble(value);
}
@Override
public ByteBuf writeBytes(ByteBuf src) {
- recordLeakNonRefCountingOperation();
+ recordLeakNonRefCountingOperation(leak);
return super.writeBytes(src);
}
@Override
public ByteBuf writeBytes(ByteBuf src, int length) {
- recordLeakNonRefCountingOperation();
+ recordLeakNonRefCountingOperation(leak);
return super.writeBytes(src, length);
}
@Override
public ByteBuf writeBytes(ByteBuf src, int srcIndex, int length) {
- recordLeakNonRefCountingOperation();
+ recordLeakNonRefCountingOperation(leak);
return super.writeBytes(src, srcIndex, length);
}
@Override
public ByteBuf writeBytes(byte[] src) {
- recordLeakNonRefCountingOperation();
+ recordLeakNonRefCountingOperation(leak);
return super.writeBytes(src);
}
@Override
public ByteBuf writeBytes(byte[] src, int srcIndex, int length) {
- recordLeakNonRefCountingOperation();
+ recordLeakNonRefCountingOperation(leak);
return super.writeBytes(src, srcIndex, length);
}
@Override
public ByteBuf writeBytes(ByteBuffer src) {
- recordLeakNonRefCountingOperation();
+ recordLeakNonRefCountingOperation(leak);
return super.writeBytes(src);
}
@Override
public int writeBytes(InputStream in, int length) throws IOException {
- recordLeakNonRefCountingOperation();
+ recordLeakNonRefCountingOperation(leak);
return super.writeBytes(in, length);
}
@Override
public int writeBytes(ScatteringByteChannel in, int length) throws IOException {
- recordLeakNonRefCountingOperation();
+ recordLeakNonRefCountingOperation(leak);
return super.writeBytes(in, length);
}
@Override
public ByteBuf writeZero(int length) {
- recordLeakNonRefCountingOperation();
+ recordLeakNonRefCountingOperation(leak);
return super.writeZero(length);
}
@Override
public int indexOf(int fromIndex, int toIndex, byte value) {
- recordLeakNonRefCountingOperation();
+ recordLeakNonRefCountingOperation(leak);
return super.indexOf(fromIndex, toIndex, value);
}
@Override
public int bytesBefore(byte value) {
- recordLeakNonRefCountingOperation();
+ recordLeakNonRefCountingOperation(leak);
return super.bytesBefore(value);
}
@Override
public int bytesBefore(int length, byte value) {
- recordLeakNonRefCountingOperation();
+ recordLeakNonRefCountingOperation(leak);
return super.bytesBefore(length, value);
}
@Override
public int bytesBefore(int index, int length, byte value) {
- recordLeakNonRefCountingOperation();
+ recordLeakNonRefCountingOperation(leak);
return super.bytesBefore(index, length, value);
}
@Override
public int forEachByte(ByteBufProcessor processor) {
- recordLeakNonRefCountingOperation();
+ recordLeakNonRefCountingOperation(leak);
return super.forEachByte(processor);
}
@Override
public int forEachByte(int index, int length, ByteBufProcessor processor) {
- recordLeakNonRefCountingOperation();
+ recordLeakNonRefCountingOperation(leak);
return super.forEachByte(index, length, processor);
}
@Override
public int forEachByteDesc(ByteBufProcessor processor) {
- recordLeakNonRefCountingOperation();
+ recordLeakNonRefCountingOperation(leak);
return super.forEachByteDesc(processor);
}
@Override
public int forEachByteDesc(int index, int length, ByteBufProcessor processor) {
- recordLeakNonRefCountingOperation();
+ recordLeakNonRefCountingOperation(leak);
return super.forEachByteDesc(index, length, processor);
}
@Override
public ByteBuf copy() {
- recordLeakNonRefCountingOperation();
+ recordLeakNonRefCountingOperation(leak);
return super.copy();
}
@Override
public ByteBuf copy(int index, int length) {
- recordLeakNonRefCountingOperation();
+ recordLeakNonRefCountingOperation(leak);
return super.copy(index, length);
}
@Override
public int nioBufferCount() {
- recordLeakNonRefCountingOperation();
+ recordLeakNonRefCountingOperation(leak);
return super.nioBufferCount();
}
@Override
public ByteBuffer nioBuffer() {
- recordLeakNonRefCountingOperation();
+ recordLeakNonRefCountingOperation(leak);
return super.nioBuffer();
}
@Override
public ByteBuffer nioBuffer(int index, int length) {
- recordLeakNonRefCountingOperation();
+ recordLeakNonRefCountingOperation(leak);
return super.nioBuffer(index, length);
}
@Override
public ByteBuffer[] nioBuffers() {
- recordLeakNonRefCountingOperation();
+ recordLeakNonRefCountingOperation(leak);
return super.nioBuffers();
}
@Override
public ByteBuffer[] nioBuffers(int index, int length) {
- recordLeakNonRefCountingOperation();
+ recordLeakNonRefCountingOperation(leak);
return super.nioBuffers(index, length);
}
@Override
public ByteBuffer internalNioBuffer(int index, int length) {
- recordLeakNonRefCountingOperation();
+ recordLeakNonRefCountingOperation(leak);
return super.internalNioBuffer(index, length);
}
@Override
public String toString(Charset charset) {
- recordLeakNonRefCountingOperation();
+ recordLeakNonRefCountingOperation(leak);
return super.toString(charset);
}
@Override
public String toString(int index, int length, Charset charset) {
- recordLeakNonRefCountingOperation();
+ recordLeakNonRefCountingOperation(leak);
return super.toString(index, length, charset);
}
@@ -740,7 +740,7 @@
@Override
public ByteBuf capacity(int newCapacity) {
- recordLeakNonRefCountingOperation();
+ recordLeakNonRefCountingOperation(leak);
return super.capacity(newCapacity);
}
}
diff -Nru netty-4.0.33/buffer/src/main/java/io/netty/buffer/AdvancedLeakAwareCompositeByteBuf.java netty-4.0.34/buffer/src/main/java/io/netty/buffer/AdvancedLeakAwareCompositeByteBuf.java
--- netty-4.0.33/buffer/src/main/java/io/netty/buffer/AdvancedLeakAwareCompositeByteBuf.java 1970-01-01 00:00:00.000000000 +0000
+++ netty-4.0.34/buffer/src/main/java/io/netty/buffer/AdvancedLeakAwareCompositeByteBuf.java 2016-01-29 08:23:46.000000000 +0000
@@ -0,0 +1,806 @@
+/*
+ * Copyright 2016 The Netty Project
+ *
+ * The Netty Project licenses this file to you under the Apache License,
+ * version 2.0 (the "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+package io.netty.buffer;
+
+
+import io.netty.util.ResourceLeak;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.channels.GatheringByteChannel;
+import java.nio.channels.ScatteringByteChannel;
+import java.nio.charset.Charset;
+import java.util.Iterator;
+import java.util.List;
+
+import static io.netty.buffer.AdvancedLeakAwareByteBuf.recordLeakNonRefCountingOperation;
+
+final class AdvancedLeakAwareCompositeByteBuf extends WrappedCompositeByteBuf {
+
+ private final ResourceLeak leak;
+
+ AdvancedLeakAwareCompositeByteBuf(CompositeByteBuf wrapped, ResourceLeak leak) {
+ super(wrapped);
+ this.leak = leak;
+ }
+
+ @Override
+ public ByteBuf order(ByteOrder endianness) {
+ recordLeakNonRefCountingOperation(leak);
+ if (order() == endianness) {
+ return this;
+ } else {
+ return new AdvancedLeakAwareByteBuf(super.order(endianness), leak);
+ }
+ }
+
+ @Override
+ public ByteBuf slice() {
+ recordLeakNonRefCountingOperation(leak);
+ return new AdvancedLeakAwareByteBuf(super.slice(), leak);
+ }
+
+ @Override
+ public ByteBuf slice(int index, int length) {
+ recordLeakNonRefCountingOperation(leak);
+ return new AdvancedLeakAwareByteBuf(super.slice(index, length), leak);
+ }
+
+ @Override
+ public ByteBuf duplicate() {
+ recordLeakNonRefCountingOperation(leak);
+ return new AdvancedLeakAwareByteBuf(super.duplicate(), leak);
+ }
+
+ @Override
+ public ByteBuf readSlice(int length) {
+ recordLeakNonRefCountingOperation(leak);
+ return new AdvancedLeakAwareByteBuf(super.readSlice(length), leak);
+ }
+
+ @Override
+ public CompositeByteBuf discardReadBytes() {
+ recordLeakNonRefCountingOperation(leak);
+ return super.discardReadBytes();
+ }
+
+ @Override
+ public CompositeByteBuf discardSomeReadBytes() {
+ recordLeakNonRefCountingOperation(leak);
+ return super.discardSomeReadBytes();
+ }
+
+ @Override
+ public CompositeByteBuf ensureWritable(int minWritableBytes) {
+ recordLeakNonRefCountingOperation(leak);
+ return super.ensureWritable(minWritableBytes);
+ }
+
+ @Override
+ public int ensureWritable(int minWritableBytes, boolean force) {
+ recordLeakNonRefCountingOperation(leak);
+ return super.ensureWritable(minWritableBytes, force);
+ }
+
+ @Override
+ public boolean getBoolean(int index) {
+ recordLeakNonRefCountingOperation(leak);
+ return super.getBoolean(index);
+ }
+
+ @Override
+ public byte getByte(int index) {
+ recordLeakNonRefCountingOperation(leak);
+ return super.getByte(index);
+ }
+
+ @Override
+ public short getUnsignedByte(int index) {
+ recordLeakNonRefCountingOperation(leak);
+ return super.getUnsignedByte(index);
+ }
+
+ @Override
+ public short getShort(int index) {
+ recordLeakNonRefCountingOperation(leak);
+ return super.getShort(index);
+ }
+
+ @Override
+ public int getUnsignedShort(int index) {
+ recordLeakNonRefCountingOperation(leak);
+ return super.getUnsignedShort(index);
+ }
+
+ @Override
+ public int getMedium(int index) {
+ recordLeakNonRefCountingOperation(leak);
+ return super.getMedium(index);
+ }
+
+ @Override
+ public int getUnsignedMedium(int index) {
+ recordLeakNonRefCountingOperation(leak);
+ return super.getUnsignedMedium(index);
+ }
+
+ @Override
+ public int getInt(int index) {
+ recordLeakNonRefCountingOperation(leak);
+ return super.getInt(index);
+ }
+
+ @Override
+ public long getUnsignedInt(int index) {
+ recordLeakNonRefCountingOperation(leak);
+ return super.getUnsignedInt(index);
+ }
+
+ @Override
+ public long getLong(int index) {
+ recordLeakNonRefCountingOperation(leak);
+ return super.getLong(index);
+ }
+
+ @Override
+ public char getChar(int index) {
+ recordLeakNonRefCountingOperation(leak);
+ return super.getChar(index);
+ }
+
+ @Override
+ public float getFloat(int index) {
+ recordLeakNonRefCountingOperation(leak);
+ return super.getFloat(index);
+ }
+
+ @Override
+ public double getDouble(int index) {
+ recordLeakNonRefCountingOperation(leak);
+ return super.getDouble(index);
+ }
+
+ @Override
+ public CompositeByteBuf getBytes(int index, ByteBuf dst) {
+ recordLeakNonRefCountingOperation(leak);
+ return super.getBytes(index, dst);
+ }
+
+ @Override
+ public CompositeByteBuf getBytes(int index, ByteBuf dst, int length) {
+ recordLeakNonRefCountingOperation(leak);
+ return super.getBytes(index, dst, length);
+ }
+
+ @Override
+ public CompositeByteBuf getBytes(int index, ByteBuf dst, int dstIndex, int length) {
+ recordLeakNonRefCountingOperation(leak);
+ return super.getBytes(index, dst, dstIndex, length);
+ }
+
+ @Override
+ public CompositeByteBuf getBytes(int index, byte[] dst) {
+ recordLeakNonRefCountingOperation(leak);
+ return super.getBytes(index, dst);
+ }
+
+ @Override
+ public CompositeByteBuf getBytes(int index, byte[] dst, int dstIndex, int length) {
+ recordLeakNonRefCountingOperation(leak);
+ return super.getBytes(index, dst, dstIndex, length);
+ }
+
+ @Override
+ public CompositeByteBuf getBytes(int index, ByteBuffer dst) {
+ recordLeakNonRefCountingOperation(leak);
+ return super.getBytes(index, dst);
+ }
+
+ @Override
+ public CompositeByteBuf getBytes(int index, OutputStream out, int length) throws IOException {
+ recordLeakNonRefCountingOperation(leak);
+ return super.getBytes(index, out, length);
+ }
+
+ @Override
+ public int getBytes(int index, GatheringByteChannel out, int length) throws IOException {
+ recordLeakNonRefCountingOperation(leak);
+ return super.getBytes(index, out, length);
+ }
+
+ @Override
+ public CompositeByteBuf setBoolean(int index, boolean value) {
+ recordLeakNonRefCountingOperation(leak);
+ return super.setBoolean(index, value);
+ }
+
+ @Override
+ public CompositeByteBuf setByte(int index, int value) {
+ recordLeakNonRefCountingOperation(leak);
+ return super.setByte(index, value);
+ }
+
+ @Override
+ public CompositeByteBuf setShort(int index, int value) {
+ recordLeakNonRefCountingOperation(leak);
+ return super.setShort(index, value);
+ }
+
+ @Override
+ public CompositeByteBuf setMedium(int index, int value) {
+ recordLeakNonRefCountingOperation(leak);
+ return super.setMedium(index, value);
+ }
+
+ @Override
+ public CompositeByteBuf setInt(int index, int value) {
+ recordLeakNonRefCountingOperation(leak);
+ return super.setInt(index, value);
+ }
+
+ @Override
+ public CompositeByteBuf setLong(int index, long value) {
+ recordLeakNonRefCountingOperation(leak);
+ return super.setLong(index, value);
+ }
+
+ @Override
+ public CompositeByteBuf setChar(int index, int value) {
+ recordLeakNonRefCountingOperation(leak);
+ return super.setChar(index, value);
+ }
+
+ @Override
+ public CompositeByteBuf setFloat(int index, float value) {
+ recordLeakNonRefCountingOperation(leak);
+ return super.setFloat(index, value);
+ }
+
+ @Override
+ public CompositeByteBuf setDouble(int index, double value) {
+ recordLeakNonRefCountingOperation(leak);
+ return super.setDouble(index, value);
+ }
+
+ @Override
+ public CompositeByteBuf setBytes(int index, ByteBuf src) {
+ recordLeakNonRefCountingOperation(leak);
+ return super.setBytes(index, src);
+ }
+
+ @Override
+ public CompositeByteBuf setBytes(int index, ByteBuf src, int length) {
+ recordLeakNonRefCountingOperation(leak);
+ return super.setBytes(index, src, length);
+ }
+
+ @Override
+ public CompositeByteBuf setBytes(int index, ByteBuf src, int srcIndex, int length) {
+ recordLeakNonRefCountingOperation(leak);
+ return super.setBytes(index, src, srcIndex, length);
+ }
+
+ @Override
+ public CompositeByteBuf setBytes(int index, byte[] src) {
+ recordLeakNonRefCountingOperation(leak);
+ return super.setBytes(index, src);
+ }
+
+ @Override
+ public CompositeByteBuf setBytes(int index, byte[] src, int srcIndex, int length) {
+ recordLeakNonRefCountingOperation(leak);
+ return super.setBytes(index, src, srcIndex, length);
+ }
+
+ @Override
+ public CompositeByteBuf setBytes(int index, ByteBuffer src) {
+ recordLeakNonRefCountingOperation(leak);
+ return super.setBytes(index, src);
+ }
+
+ @Override
+ public int setBytes(int index, InputStream in, int length) throws IOException {
+ recordLeakNonRefCountingOperation(leak);
+ return super.setBytes(index, in, length);
+ }
+
+ @Override
+ public int setBytes(int index, ScatteringByteChannel in, int length) throws IOException {
+ recordLeakNonRefCountingOperation(leak);
+ return super.setBytes(index, in, length);
+ }
+
+ @Override
+ public CompositeByteBuf setZero(int index, int length) {
+ recordLeakNonRefCountingOperation(leak);
+ return super.setZero(index, length);
+ }
+
+ @Override
+ public boolean readBoolean() {
+ recordLeakNonRefCountingOperation(leak);
+ return super.readBoolean();
+ }
+
+ @Override
+ public byte readByte() {
+ recordLeakNonRefCountingOperation(leak);
+ return super.readByte();
+ }
+
+ @Override
+ public short readUnsignedByte() {
+ recordLeakNonRefCountingOperation(leak);
+ return super.readUnsignedByte();
+ }
+
+ @Override
+ public short readShort() {
+ recordLeakNonRefCountingOperation(leak);
+ return super.readShort();
+ }
+
+ @Override
+ public int readUnsignedShort() {
+ recordLeakNonRefCountingOperation(leak);
+ return super.readUnsignedShort();
+ }
+
+ @Override
+ public int readMedium() {
+ recordLeakNonRefCountingOperation(leak);
+ return super.readMedium();
+ }
+
+ @Override
+ public int readUnsignedMedium() {
+ recordLeakNonRefCountingOperation(leak);
+ return super.readUnsignedMedium();
+ }
+
+ @Override
+ public int readInt() {
+ recordLeakNonRefCountingOperation(leak);
+ return super.readInt();
+ }
+
+ @Override
+ public long readUnsignedInt() {
+ recordLeakNonRefCountingOperation(leak);
+ return super.readUnsignedInt();
+ }
+
+ @Override
+ public long readLong() {
+ recordLeakNonRefCountingOperation(leak);
+ return super.readLong();
+ }
+
+ @Override
+ public char readChar() {
+ recordLeakNonRefCountingOperation(leak);
+ return super.readChar();
+ }
+
+ @Override
+ public float readFloat() {
+ recordLeakNonRefCountingOperation(leak);
+ return super.readFloat();
+ }
+
+ @Override
+ public double readDouble() {
+ recordLeakNonRefCountingOperation(leak);
+ return super.readDouble();
+ }
+
+ @Override
+ public ByteBuf readBytes(int length) {
+ recordLeakNonRefCountingOperation(leak);
+ return super.readBytes(length);
+ }
+
+ @Override
+ public CompositeByteBuf readBytes(ByteBuf dst) {
+ recordLeakNonRefCountingOperation(leak);
+ return super.readBytes(dst);
+ }
+
+ @Override
+ public CompositeByteBuf readBytes(ByteBuf dst, int length) {
+ recordLeakNonRefCountingOperation(leak);
+ return super.readBytes(dst, length);
+ }
+
+ @Override
+ public CompositeByteBuf readBytes(ByteBuf dst, int dstIndex, int length) {
+ recordLeakNonRefCountingOperation(leak);
+ return super.readBytes(dst, dstIndex, length);
+ }
+
+ @Override
+ public CompositeByteBuf readBytes(byte[] dst) {
+ recordLeakNonRefCountingOperation(leak);
+ return super.readBytes(dst);
+ }
+
+ @Override
+ public CompositeByteBuf readBytes(byte[] dst, int dstIndex, int length) {
+ recordLeakNonRefCountingOperation(leak);
+ return super.readBytes(dst, dstIndex, length);
+ }
+
+ @Override
+ public CompositeByteBuf readBytes(ByteBuffer dst) {
+ recordLeakNonRefCountingOperation(leak);
+ return super.readBytes(dst);
+ }
+
+ @Override
+ public CompositeByteBuf readBytes(OutputStream out, int length) throws IOException {
+ recordLeakNonRefCountingOperation(leak);
+ return super.readBytes(out, length);
+ }
+
+ @Override
+ public int readBytes(GatheringByteChannel out, int length) throws IOException {
+ recordLeakNonRefCountingOperation(leak);
+ return super.readBytes(out, length);
+ }
+
+ @Override
+ public CompositeByteBuf skipBytes(int length) {
+ recordLeakNonRefCountingOperation(leak);
+ return super.skipBytes(length);
+ }
+
+ @Override
+ public CompositeByteBuf writeBoolean(boolean value) {
+ recordLeakNonRefCountingOperation(leak);
+ return super.writeBoolean(value);
+ }
+
+ @Override
+ public CompositeByteBuf writeByte(int value) {
+ recordLeakNonRefCountingOperation(leak);
+ return super.writeByte(value);
+ }
+
+ @Override
+ public CompositeByteBuf writeShort(int value) {
+ recordLeakNonRefCountingOperation(leak);
+ return super.writeShort(value);
+ }
+
+ @Override
+ public CompositeByteBuf writeMedium(int value) {
+ recordLeakNonRefCountingOperation(leak);
+ return super.writeMedium(value);
+ }
+
+ @Override
+ public CompositeByteBuf writeInt(int value) {
+ recordLeakNonRefCountingOperation(leak);
+ return super.writeInt(value);
+ }
+
+ @Override
+ public CompositeByteBuf writeLong(long value) {
+ recordLeakNonRefCountingOperation(leak);
+ return super.writeLong(value);
+ }
+
+ @Override
+ public CompositeByteBuf writeChar(int value) {
+ recordLeakNonRefCountingOperation(leak);
+ return super.writeChar(value);
+ }
+
+ @Override
+ public CompositeByteBuf writeFloat(float value) {
+ recordLeakNonRefCountingOperation(leak);
+ return super.writeFloat(value);
+ }
+
+ @Override
+ public CompositeByteBuf writeDouble(double value) {
+ recordLeakNonRefCountingOperation(leak);
+ return super.writeDouble(value);
+ }
+
+ @Override
+ public CompositeByteBuf writeBytes(ByteBuf src) {
+ recordLeakNonRefCountingOperation(leak);
+ return super.writeBytes(src);
+ }
+
+ @Override
+ public CompositeByteBuf writeBytes(ByteBuf src, int length) {
+ recordLeakNonRefCountingOperation(leak);
+ return super.writeBytes(src, length);
+ }
+
+ @Override
+ public CompositeByteBuf writeBytes(ByteBuf src, int srcIndex, int length) {
+ recordLeakNonRefCountingOperation(leak);
+ return super.writeBytes(src, srcIndex, length);
+ }
+
+ @Override
+ public CompositeByteBuf writeBytes(byte[] src) {
+ recordLeakNonRefCountingOperation(leak);
+ return super.writeBytes(src);
+ }
+
+ @Override
+ public CompositeByteBuf writeBytes(byte[] src, int srcIndex, int length) {
+ recordLeakNonRefCountingOperation(leak);
+ return super.writeBytes(src, srcIndex, length);
+ }
+
+ @Override
+ public CompositeByteBuf writeBytes(ByteBuffer src) {
+ recordLeakNonRefCountingOperation(leak);
+ return super.writeBytes(src);
+ }
+
+ @Override
+ public int writeBytes(InputStream in, int length) throws IOException {
+ recordLeakNonRefCountingOperation(leak);
+ return super.writeBytes(in, length);
+ }
+
+ @Override
+ public int writeBytes(ScatteringByteChannel in, int length) throws IOException {
+ recordLeakNonRefCountingOperation(leak);
+ return super.writeBytes(in, length);
+ }
+
+ @Override
+ public CompositeByteBuf writeZero(int length) {
+ recordLeakNonRefCountingOperation(leak);
+ return super.writeZero(length);
+ }
+
+ @Override
+ public int indexOf(int fromIndex, int toIndex, byte value) {
+ recordLeakNonRefCountingOperation(leak);
+ return super.indexOf(fromIndex, toIndex, value);
+ }
+
+ @Override
+ public int bytesBefore(byte value) {
+ recordLeakNonRefCountingOperation(leak);
+ return super.bytesBefore(value);
+ }
+
+ @Override
+ public int bytesBefore(int length, byte value) {
+ recordLeakNonRefCountingOperation(leak);
+ return super.bytesBefore(length, value);
+ }
+
+ @Override
+ public int bytesBefore(int index, int length, byte value) {
+ recordLeakNonRefCountingOperation(leak);
+ return super.bytesBefore(index, length, value);
+ }
+
+ @Override
+ public int forEachByte(ByteBufProcessor processor) {
+ recordLeakNonRefCountingOperation(leak);
+ return super.forEachByte(processor);
+ }
+
+ @Override
+ public int forEachByte(int index, int length, ByteBufProcessor processor) {
+ recordLeakNonRefCountingOperation(leak);
+ return super.forEachByte(index, length, processor);
+ }
+
+ @Override
+ public int forEachByteDesc(ByteBufProcessor processor) {
+ recordLeakNonRefCountingOperation(leak);
+ return super.forEachByteDesc(processor);
+ }
+
+ @Override
+ public int forEachByteDesc(int index, int length, ByteBufProcessor processor) {
+ recordLeakNonRefCountingOperation(leak);
+ return super.forEachByteDesc(index, length, processor);
+ }
+
+ @Override
+ public ByteBuf copy() {
+ recordLeakNonRefCountingOperation(leak);
+ return super.copy();
+ }
+
+ @Override
+ public ByteBuf copy(int index, int length) {
+ recordLeakNonRefCountingOperation(leak);
+ return super.copy(index, length);
+ }
+
+ @Override
+ public int nioBufferCount() {
+ recordLeakNonRefCountingOperation(leak);
+ return super.nioBufferCount();
+ }
+
+ @Override
+ public ByteBuffer nioBuffer() {
+ recordLeakNonRefCountingOperation(leak);
+ return super.nioBuffer();
+ }
+
+ @Override
+ public ByteBuffer nioBuffer(int index, int length) {
+ recordLeakNonRefCountingOperation(leak);
+ return super.nioBuffer(index, length);
+ }
+
+ @Override
+ public ByteBuffer[] nioBuffers() {
+ recordLeakNonRefCountingOperation(leak);
+ return super.nioBuffers();
+ }
+
+ @Override
+ public ByteBuffer[] nioBuffers(int index, int length) {
+ recordLeakNonRefCountingOperation(leak);
+ return super.nioBuffers(index, length);
+ }
+
+ @Override
+ public ByteBuffer internalNioBuffer(int index, int length) {
+ recordLeakNonRefCountingOperation(leak);
+ return super.internalNioBuffer(index, length);
+ }
+
+ @Override
+ public String toString(Charset charset) {
+ recordLeakNonRefCountingOperation(leak);
+ return super.toString(charset);
+ }
+
+ @Override
+ public String toString(int index, int length, Charset charset) {
+ recordLeakNonRefCountingOperation(leak);
+ return super.toString(index, length, charset);
+ }
+
+ @Override
+ public CompositeByteBuf capacity(int newCapacity) {
+ recordLeakNonRefCountingOperation(leak);
+ return super.capacity(newCapacity);
+ }
+
+ @Override
+ public CompositeByteBuf addComponent(ByteBuf buffer) {
+ recordLeakNonRefCountingOperation(leak);
+ return super.addComponent(buffer);
+ }
+
+ @Override
+ public CompositeByteBuf addComponents(ByteBuf... buffers) {
+ recordLeakNonRefCountingOperation(leak);
+ return super.addComponents(buffers);
+ }
+
+ @Override
+ public CompositeByteBuf addComponents(Iterable buffers) {
+ recordLeakNonRefCountingOperation(leak);
+ return super.addComponents(buffers);
+ }
+
+ @Override
+ public CompositeByteBuf addComponent(int cIndex, ByteBuf buffer) {
+ recordLeakNonRefCountingOperation(leak);
+ return super.addComponent(cIndex, buffer);
+ }
+
+ @Override
+ public CompositeByteBuf addComponents(int cIndex, ByteBuf... buffers) {
+ recordLeakNonRefCountingOperation(leak);
+ return super.addComponents(cIndex, buffers);
+ }
+
+ @Override
+ public CompositeByteBuf removeComponent(int cIndex) {
+ recordLeakNonRefCountingOperation(leak);
+ return super.removeComponent(cIndex);
+ }
+
+ @Override
+ public CompositeByteBuf addComponents(int cIndex, Iterable buffers) {
+ recordLeakNonRefCountingOperation(leak);
+ return super.addComponents(cIndex, buffers);
+ }
+
+ @Override
+ public CompositeByteBuf removeComponents(int cIndex, int numComponents) {
+ recordLeakNonRefCountingOperation(leak);
+ return super.removeComponents(cIndex, numComponents);
+ }
+
+ @Override
+ public Iterator iterator() {
+ recordLeakNonRefCountingOperation(leak);
+ return super.iterator();
+ }
+
+ @Override
+ public List decompose(int offset, int length) {
+ recordLeakNonRefCountingOperation(leak);
+ return super.decompose(offset, length);
+ }
+
+ @Override
+ public CompositeByteBuf consolidate() {
+ recordLeakNonRefCountingOperation(leak);
+ return super.consolidate();
+ }
+
+ @Override
+ public CompositeByteBuf discardReadComponents() {
+ recordLeakNonRefCountingOperation(leak);
+ return super.discardReadComponents();
+ }
+
+ @Override
+ public CompositeByteBuf consolidate(int cIndex, int numComponents) {
+ recordLeakNonRefCountingOperation(leak);
+ return super.consolidate(cIndex, numComponents);
+ }
+
+ @Override
+ public CompositeByteBuf retain() {
+ leak.record();
+ return super.retain();
+ }
+
+ @Override
+ public CompositeByteBuf retain(int increment) {
+ leak.record();
+ return super.retain(increment);
+ }
+
+ @Override
+ public boolean release() {
+ boolean deallocated = super.release();
+ if (deallocated) {
+ leak.close();
+ } else {
+ leak.record();
+ }
+ return deallocated;
+ }
+
+ @Override
+ public boolean release(int decrement) {
+ boolean deallocated = super.release(decrement);
+ if (deallocated) {
+ leak.close();
+ } else {
+ leak.record();
+ }
+ return deallocated;
+ }
+}
diff -Nru netty-4.0.33/buffer/src/main/java/io/netty/buffer/ByteBuf.java netty-4.0.34/buffer/src/main/java/io/netty/buffer/ByteBuf.java
--- netty-4.0.33/buffer/src/main/java/io/netty/buffer/ByteBuf.java 2015-11-03 13:18:17.000000000 +0000
+++ netty-4.0.34/buffer/src/main/java/io/netty/buffer/ByteBuf.java 2016-01-29 08:23:46.000000000 +0000
@@ -95,7 +95,7 @@
*
Writable bytes
*
* This segment is a undefined space which needs to be filled. Any operation
- * whose name ends with {@code write} will write the data at the current
+ * whose name starts with {@code write} will write the data at the current
* {@link #writerIndex() writerIndex} and increase it by the number of written
* bytes. If the argument of the write operation is also a {@link ByteBuf},
* and no source index is specified, the specified buffer's
diff -Nru netty-4.0.33/buffer/src/main/java/io/netty/buffer/ByteBufUtil.java netty-4.0.34/buffer/src/main/java/io/netty/buffer/ByteBufUtil.java
--- netty-4.0.33/buffer/src/main/java/io/netty/buffer/ByteBufUtil.java 2015-11-03 13:18:17.000000000 +0000
+++ netty-4.0.34/buffer/src/main/java/io/netty/buffer/ByteBufUtil.java 2016-01-29 08:23:46.000000000 +0000
@@ -19,7 +19,6 @@
import io.netty.util.Recycler;
import io.netty.util.Recycler.Handle;
import io.netty.util.concurrent.FastThreadLocal;
-import io.netty.util.internal.ObjectUtil;
import io.netty.util.internal.PlatformDependent;
import io.netty.util.internal.StringUtil;
import io.netty.util.internal.SystemPropertyUtil;
@@ -36,6 +35,11 @@
import java.nio.charset.CoderResult;
import java.util.Locale;
+import static io.netty.util.internal.MathUtil.isOutOfBounds;
+import static io.netty.util.internal.ObjectUtil.checkNotNull;
+import static io.netty.util.internal.StringUtil.NEWLINE;
+import static io.netty.util.internal.StringUtil.isSurrogate;
+
/**
* A collection of utility methods that is related with handling {@link ByteBuf},
* such as the generation of hex dump and swapping an integer's byte order.
@@ -51,71 +55,11 @@
};
private static final int MAX_CHAR_BUFFER_SIZE;
- private static final char[] HEXDUMP_TABLE = new char[256 * 4];
- private static final String NEWLINE = StringUtil.NEWLINE;
- private static final String[] BYTE2HEX = new String[256];
- private static final String[] HEXPADDING = new String[16];
- private static final String[] BYTEPADDING = new String[16];
- private static final char[] BYTE2CHAR = new char[256];
- private static final String[] HEXDUMP_ROWPREFIXES = new String[65536 >>> 4];
+ private static final int THREAD_LOCAL_BUFFER_SIZE;
static final ByteBufAllocator DEFAULT_ALLOCATOR;
- private static final int THREAD_LOCAL_BUFFER_SIZE;
-
static {
- final char[] DIGITS = "0123456789abcdef".toCharArray();
- for (int i = 0; i < 256; i ++) {
- HEXDUMP_TABLE[ i << 1 ] = DIGITS[i >>> 4 & 0x0F];
- HEXDUMP_TABLE[(i << 1) + 1] = DIGITS[i & 0x0F];
- }
-
- int i;
-
- // Generate the lookup table for byte-to-hex-dump conversion
- for (i = 0; i < BYTE2HEX.length; i ++) {
- BYTE2HEX[i] = ' ' + StringUtil.byteToHexStringPadded(i);
- }
-
- // Generate the lookup table for hex dump paddings
- for (i = 0; i < HEXPADDING.length; i ++) {
- int padding = HEXPADDING.length - i;
- StringBuilder buf = new StringBuilder(padding * 3);
- for (int j = 0; j < padding; j ++) {
- buf.append(" ");
- }
- HEXPADDING[i] = buf.toString();
- }
-
- // Generate the lookup table for byte dump paddings
- for (i = 0; i < BYTEPADDING.length; i ++) {
- int padding = BYTEPADDING.length - i;
- StringBuilder buf = new StringBuilder(padding);
- for (int j = 0; j < padding; j ++) {
- buf.append(' ');
- }
- BYTEPADDING[i] = buf.toString();
- }
-
- // Generate the lookup table for byte-to-char conversion
- for (i = 0; i < BYTE2CHAR.length; i ++) {
- if (i <= 0x1f || i >= 0x7f) {
- BYTE2CHAR[i] = '.';
- } else {
- BYTE2CHAR[i] = (char) i;
- }
- }
-
- // Generate the lookup table for the start-offset header in each row (up to 64KiB).
- for (i = 0; i < HEXDUMP_ROWPREFIXES.length; i ++) {
- StringBuilder buf = new StringBuilder(12);
- buf.append(NEWLINE);
- buf.append(Long.toHexString(i << 4 & 0xFFFFFFFFL | 0x100000000L));
- buf.setCharAt(buf.length() - 9, '|');
- buf.append('|');
- HEXDUMP_ROWPREFIXES[i] = buf.toString();
- }
-
String allocType = SystemPropertyUtil.get("io.netty.allocator.type", "unpooled").toLowerCase(Locale.US).trim();
ByteBufAllocator alloc;
if ("unpooled".equals(allocType)) {
@@ -151,28 +95,29 @@
* of the specified buffer's sub-region.
*/
public static String hexDump(ByteBuf buffer, int fromIndex, int length) {
- if (length < 0) {
- throw new IllegalArgumentException("length: " + length);
- }
- if (length == 0) {
- return "";
- }
-
- int endIndex = fromIndex + length;
- char[] buf = new char[length << 1];
+ return HexUtil.hexDump(buffer, fromIndex, length);
+ }
- int srcIdx = fromIndex;
- int dstIdx = 0;
- for (; srcIdx < endIndex; srcIdx ++, dstIdx += 2) {
- System.arraycopy(
- HEXDUMP_TABLE, buffer.getUnsignedByte(srcIdx) << 1,
- buf, dstIdx, 2);
- }
+ /**
+<<<<<<< HEAD
+=======
+ * Returns a hex dump
+ * of the specified byte array.
+ */
+ public static String hexDump(byte[] array) {
+ return hexDump(array, 0, array.length);
+ }
- return new String(buf);
+ /**
+ * Returns a hex dump
+ * of the specified byte array's sub-region.
+ */
+ public static String hexDump(byte[] array, int fromIndex, int length) {
+ return HexUtil.hexDump(array, fromIndex, length);
}
/**
+>>>>>>> e5386b0... Move Hex dump related util from ByteBufUtil to inner class
* Calculates the hash code of the specified buffer. This method is
* useful when implementing a new buffer type.
*/
@@ -435,6 +380,31 @@
} else if (c < 0x800) {
buffer._setByte(writerIndex++, (byte) (0xc0 | (c >> 6)));
buffer._setByte(writerIndex++, (byte) (0x80 | (c & 0x3f)));
+ } else if (isSurrogate(c)) {
+ if (!Character.isHighSurrogate(c)) {
+ throw new IllegalArgumentException("Invalid encoding. " +
+ "Expected high (leading) surrogate at index " + i + " but got " + c);
+ }
+ final char c2;
+ try {
+ // Surrogate Pair consumes 2 characters. Optimistically try to get the next character to avoid
+ // duplicate bounds checking with charAt. If an IndexOutOfBoundsException is thrown we will
+ // re-throw a more informative exception describing the problem.
+ c2 = seq.charAt(++i);
+ } catch (IndexOutOfBoundsException e) {
+ throw new IllegalArgumentException("Underflow. " +
+ "Expected low (trailing) surrogate at index " + i + " but no more characters found.", e);
+ }
+ if (!Character.isLowSurrogate(c2)) {
+ throw new IllegalArgumentException("Invalid encoding. " +
+ "Expected low (trailing) surrogate at index " + i + " but got " + c2);
+ }
+ int codePoint = Character.toCodePoint(c, c2);
+ // See http://www.unicode.org/versions/Unicode7.0.0/ch03.pdf#G2630.
+ buffer._setByte(writerIndex++, (byte) (0xf0 | (codePoint >> 18)));
+ buffer._setByte(writerIndex++, (byte) (0x80 | ((codePoint >> 12) & 0x3f)));
+ buffer._setByte(writerIndex++, (byte) (0x80 | ((codePoint >> 6) & 0x3f)));
+ buffer._setByte(writerIndex++, (byte) (0x80 | (codePoint & 0x3f)));
} else {
buffer._setByte(writerIndex++, (byte) (0xe0 | (c >> 12)));
buffer._setByte(writerIndex++, (byte) (0x80 | ((c >> 6) & 0x3f)));
@@ -555,7 +525,7 @@
try {
buffer.writeBytes(src, readerIndex, len);
// Use internalNioBuffer(...) to reduce object creation.
- decodeString(decoder, buffer.internalNioBuffer(readerIndex, len), dst);
+ decodeString(decoder, buffer.internalNioBuffer(0, len), dst);
} finally {
// Release the temporary buffer again.
buffer.release();
@@ -591,14 +561,7 @@
* starting at the given {@code offset} using the given {@code length}.
*/
public static String prettyHexDump(ByteBuf buffer, int offset, int length) {
- if (length == 0) {
- return StringUtil.EMPTY_STRING;
- } else {
- int rows = length / 16 + (length % 15 == 0? 0 : 1) + 4;
- StringBuilder buf = new StringBuilder(rows * 80);
- appendPrettyHexDump(buf, buffer, offset, length);
- return buf.toString();
- }
+ return HexUtil.prettyHexDump(buffer, offset, length);
}
/**
@@ -615,79 +578,201 @@
* the given {@code length}.
*/
public static void appendPrettyHexDump(StringBuilder dump, ByteBuf buf, int offset, int length) {
- if (offset < 0 || length > ObjectUtil.checkNotNull(buf, "buf").capacity() - offset) {
- throw new IndexOutOfBoundsException(
- "expected: " + "0 <= offset(" + offset + ") <= offset + length(" + length
- + ") <= " + "buf.capacity(" + buf.capacity() + ')');
- }
- if (length == 0) {
- return;
- }
- dump.append(
- " +-------------------------------------------------+" +
- NEWLINE + " | 0 1 2 3 4 5 6 7 8 9 a b c d e f |" +
- NEWLINE + "+--------+-------------------------------------------------+----------------+");
+ HexUtil.appendPrettyHexDump(dump, buf, offset, length);
+ }
+
+ /* Separate class so that the expensive static initialization is only done when needed */
+ private static final class HexUtil {
- final int startIndex = offset;
- final int fullRows = length >>> 4;
- final int remainder = length & 0xF;
+ private static final char[] BYTE2CHAR = new char[256];
+ private static final char[] HEXDUMP_TABLE = new char[256 * 4];
+ private static final String[] HEXPADDING = new String[16];
+ private static final String[] HEXDUMP_ROWPREFIXES = new String[65536 >>> 4];
+ private static final String[] BYTE2HEX = new String[256];
+ private static final String[] BYTEPADDING = new String[16];
+
+ static {
+ final char[] DIGITS = "0123456789abcdef".toCharArray();
+ for (int i = 0; i < 256; i ++) {
+ HEXDUMP_TABLE[ i << 1 ] = DIGITS[i >>> 4 & 0x0F];
+ HEXDUMP_TABLE[(i << 1) + 1] = DIGITS[i & 0x0F];
+ }
+
+ int i;
+
+ // Generate the lookup table for hex dump paddings
+ for (i = 0; i < HEXPADDING.length; i ++) {
+ int padding = HEXPADDING.length - i;
+ StringBuilder buf = new StringBuilder(padding * 3);
+ for (int j = 0; j < padding; j ++) {
+ buf.append(" ");
+ }
+ HEXPADDING[i] = buf.toString();
+ }
- // Dump the rows which have 16 bytes.
- for (int row = 0; row < fullRows; row ++) {
- int rowStartIndex = (row << 4) + startIndex;
+ // Generate the lookup table for the start-offset header in each row (up to 64KiB).
+ for (i = 0; i < HEXDUMP_ROWPREFIXES.length; i ++) {
+ StringBuilder buf = new StringBuilder(12);
+ buf.append(NEWLINE);
+ buf.append(Long.toHexString(i << 4 & 0xFFFFFFFFL | 0x100000000L));
+ buf.setCharAt(buf.length() - 9, '|');
+ buf.append('|');
+ HEXDUMP_ROWPREFIXES[i] = buf.toString();
+ }
+
+ // Generate the lookup table for byte-to-hex-dump conversion
+ for (i = 0; i < BYTE2HEX.length; i ++) {
+ BYTE2HEX[i] = ' ' + StringUtil.byteToHexStringPadded(i);
+ }
+
+ // Generate the lookup table for byte dump paddings
+ for (i = 0; i < BYTEPADDING.length; i ++) {
+ int padding = BYTEPADDING.length - i;
+ StringBuilder buf = new StringBuilder(padding);
+ for (int j = 0; j < padding; j ++) {
+ buf.append(' ');
+ }
+ BYTEPADDING[i] = buf.toString();
+ }
- // Per-row prefix.
- appendHexDumpRowPrefix(dump, row, rowStartIndex);
+ // Generate the lookup table for byte-to-char conversion
+ for (i = 0; i < BYTE2CHAR.length; i ++) {
+ if (i <= 0x1f || i >= 0x7f) {
+ BYTE2CHAR[i] = '.';
+ } else {
+ BYTE2CHAR[i] = (char) i;
+ }
+ }
+ }
- // Hex dump
- int rowEndIndex = rowStartIndex + 16;
- for (int j = rowStartIndex; j < rowEndIndex; j ++) {
- dump.append(BYTE2HEX[buf.getUnsignedByte(j)]);
+ private static String hexDump(ByteBuf buffer, int fromIndex, int length) {
+ if (length < 0) {
+ throw new IllegalArgumentException("length: " + length);
+ }
+ if (length == 0) {
+ return "";
}
- dump.append(" |");
- // ASCII dump
- for (int j = rowStartIndex; j < rowEndIndex; j ++) {
- dump.append(BYTE2CHAR[buf.getUnsignedByte(j)]);
+ int endIndex = fromIndex + length;
+ char[] buf = new char[length << 1];
+
+ int srcIdx = fromIndex;
+ int dstIdx = 0;
+ for (; srcIdx < endIndex; srcIdx ++, dstIdx += 2) {
+ System.arraycopy(
+ HEXDUMP_TABLE, buffer.getUnsignedByte(srcIdx) << 1,
+ buf, dstIdx, 2);
}
- dump.append('|');
+
+ return new String(buf);
}
- // Dump the last row which has less than 16 bytes.
- if (remainder != 0) {
- int rowStartIndex = (fullRows << 4) + startIndex;
- appendHexDumpRowPrefix(dump, fullRows, rowStartIndex);
+ private static String hexDump(byte[] array, int fromIndex, int length) {
+ if (length < 0) {
+ throw new IllegalArgumentException("length: " + length);
+ }
+ if (length == 0) {
+ return "";
+ }
+
+ int endIndex = fromIndex + length;
+ char[] buf = new char[length << 1];
- // Hex dump
- int rowEndIndex = rowStartIndex + remainder;
- for (int j = rowStartIndex; j < rowEndIndex; j ++) {
- dump.append(BYTE2HEX[buf.getUnsignedByte(j)]);
+ int srcIdx = fromIndex;
+ int dstIdx = 0;
+ for (; srcIdx < endIndex; srcIdx ++, dstIdx += 2) {
+ System.arraycopy(
+ HEXDUMP_TABLE, (array[srcIdx] & 0xFF) << 1,
+ buf, dstIdx, 2);
}
- dump.append(HEXPADDING[remainder]);
- dump.append(" |");
- // Ascii dump
- for (int j = rowStartIndex; j < rowEndIndex; j ++) {
- dump.append(BYTE2CHAR[buf.getUnsignedByte(j)]);
+ return new String(buf);
+ }
+
+ private static String prettyHexDump(ByteBuf buffer, int offset, int length) {
+ if (length == 0) {
+ return StringUtil.EMPTY_STRING;
+ } else {
+ int rows = length / 16 + (length % 15 == 0? 0 : 1) + 4;
+ StringBuilder buf = new StringBuilder(rows * 80);
+ appendPrettyHexDump(buf, buffer, offset, length);
+ return buf.toString();
}
- dump.append(BYTEPADDING[remainder]);
- dump.append('|');
}
- dump.append(NEWLINE + "+--------+-------------------------------------------------+----------------+");
- }
+ private static void appendPrettyHexDump(StringBuilder dump, ByteBuf buf, int offset, int length) {
+ if (isOutOfBounds(offset, length, buf.capacity())) {
+ throw new IndexOutOfBoundsException(
+ "expected: " + "0 <= offset(" + offset + ") <= offset + length(" + length
+ + ") <= " + "buf.capacity(" + buf.capacity() + ')');
+ }
+ if (length == 0) {
+ return;
+ }
+ dump.append(
+ " +-------------------------------------------------+" +
+ NEWLINE + " | 0 1 2 3 4 5 6 7 8 9 a b c d e f |" +
+ NEWLINE + "+--------+-------------------------------------------------+----------------+");
+
+ final int startIndex = offset;
+ final int fullRows = length >>> 4;
+ final int remainder = length & 0xF;
+
+ // Dump the rows which have 16 bytes.
+ for (int row = 0; row < fullRows; row ++) {
+ int rowStartIndex = (row << 4) + startIndex;
+
+ // Per-row prefix.
+ appendHexDumpRowPrefix(dump, row, rowStartIndex);
+
+ // Hex dump
+ int rowEndIndex = rowStartIndex + 16;
+ for (int j = rowStartIndex; j < rowEndIndex; j ++) {
+ dump.append(BYTE2HEX[buf.getUnsignedByte(j)]);
+ }
+ dump.append(" |");
- /**
- * Appends the prefix of each hex dump row. Uses the look-up table for the buffer <= 64 KiB.
- */
- private static void appendHexDumpRowPrefix(StringBuilder dump, int row, int rowStartIndex) {
- if (row < HEXDUMP_ROWPREFIXES.length) {
- dump.append(HEXDUMP_ROWPREFIXES[row]);
- } else {
- dump.append(NEWLINE);
- dump.append(Long.toHexString(rowStartIndex & 0xFFFFFFFFL | 0x100000000L));
- dump.setCharAt(dump.length() - 9, '|');
- dump.append('|');
+ // ASCII dump
+ for (int j = rowStartIndex; j < rowEndIndex; j ++) {
+ dump.append(BYTE2CHAR[buf.getUnsignedByte(j)]);
+ }
+ dump.append('|');
+ }
+
+ // Dump the last row which has less than 16 bytes.
+ if (remainder != 0) {
+ int rowStartIndex = (fullRows << 4) + startIndex;
+ appendHexDumpRowPrefix(dump, fullRows, rowStartIndex);
+
+ // Hex dump
+ int rowEndIndex = rowStartIndex + remainder;
+ for (int j = rowStartIndex; j < rowEndIndex; j ++) {
+ dump.append(BYTE2HEX[buf.getUnsignedByte(j)]);
+ }
+ dump.append(HEXPADDING[remainder]);
+ dump.append(" |");
+
+ // Ascii dump
+ for (int j = rowStartIndex; j < rowEndIndex; j ++) {
+ dump.append(BYTE2CHAR[buf.getUnsignedByte(j)]);
+ }
+ dump.append(BYTEPADDING[remainder]);
+ dump.append('|');
+ }
+
+ dump.append(NEWLINE +
+ "+--------+-------------------------------------------------+----------------+");
+ }
+
+ private static void appendHexDumpRowPrefix(StringBuilder dump, int row, int rowStartIndex) {
+ if (row < HEXDUMP_ROWPREFIXES.length) {
+ dump.append(HEXDUMP_ROWPREFIXES[row]);
+ } else {
+ dump.append(NEWLINE);
+ dump.append(Long.toHexString(rowStartIndex & 0xFFFFFFFFL | 0x100000000L));
+ dump.setCharAt(dump.length() - 9, '|');
+ dump.append('|');
+ }
}
}
diff -Nru netty-4.0.33/buffer/src/main/java/io/netty/buffer/CompositeByteBuf.java netty-4.0.34/buffer/src/main/java/io/netty/buffer/CompositeByteBuf.java
--- netty-4.0.33/buffer/src/main/java/io/netty/buffer/CompositeByteBuf.java 2015-11-03 13:18:17.000000000 +0000
+++ netty-4.0.34/buffer/src/main/java/io/netty/buffer/CompositeByteBuf.java 2016-01-29 08:23:46.000000000 +0000
@@ -15,7 +15,6 @@
*/
package io.netty.buffer;
-import io.netty.util.ResourceLeak;
import io.netty.util.internal.EmptyArrays;
import java.io.IOException;
@@ -44,10 +43,9 @@
private static final ByteBuffer EMPTY_NIO_BUFFER = Unpooled.EMPTY_BUFFER.nioBuffer();
private static final Iterator EMPTY_ITERATOR = Collections.emptyList().iterator();
- private final ResourceLeak leak;
private final ByteBufAllocator alloc;
private final boolean direct;
- private final List components = new ArrayList();
+ private final List components;
private final int maxNumComponents;
private boolean freed;
@@ -60,7 +58,7 @@
this.alloc = alloc;
this.direct = direct;
this.maxNumComponents = maxNumComponents;
- leak = leakDetector.open(this);
+ components = newList(maxNumComponents);
}
public CompositeByteBuf(ByteBufAllocator alloc, boolean direct, int maxNumComponents, ByteBuf... buffers) {
@@ -76,11 +74,11 @@
this.alloc = alloc;
this.direct = direct;
this.maxNumComponents = maxNumComponents;
+ components = newList(maxNumComponents);
addComponents0(0, buffers);
consolidateIfNeeded();
setIndex(0, capacity());
- leak = leakDetector.open(this);
}
public CompositeByteBuf(
@@ -97,10 +95,24 @@
this.alloc = alloc;
this.direct = direct;
this.maxNumComponents = maxNumComponents;
+ components = newList(maxNumComponents);
+
addComponents0(0, buffers);
consolidateIfNeeded();
setIndex(0, capacity());
- leak = leakDetector.open(this);
+ }
+
+ private static List newList(int maxNumComponents) {
+ return new ArrayList(Math.min(AbstractByteBufAllocator.DEFAULT_MAX_COMPONENTS, maxNumComponents));
+ }
+
+ // Special constructor used by WrappedCompositeByteBuf
+ CompositeByteBuf(ByteBufAllocator alloc) {
+ super(Integer.MAX_VALUE);
+ this.alloc = alloc;
+ direct = false;
+ maxNumComponents = 0;
+ components = Collections.emptyList();
}
/**
@@ -1624,10 +1636,6 @@
for (int i = 0; i < size; i++) {
components.get(i).freeIfNecessary();
}
-
- if (leak != null) {
- leak.close();
- }
}
@Override
diff -Nru netty-4.0.33/buffer/src/main/java/io/netty/buffer/PooledByteBufAllocator.java netty-4.0.34/buffer/src/main/java/io/netty/buffer/PooledByteBufAllocator.java
--- netty-4.0.33/buffer/src/main/java/io/netty/buffer/PooledByteBufAllocator.java 2015-11-03 13:18:17.000000000 +0000
+++ netty-4.0.34/buffer/src/main/java/io/netty/buffer/PooledByteBufAllocator.java 2016-01-29 08:23:46.000000000 +0000
@@ -280,6 +280,55 @@
return toLeakAwareBuffer(buf);
}
+ /**
+ * Default number of heap areanas - System Property: io.netty.allocator.numHeapArenas - default 2 * cores
+ */
+ public static int defaultNumHeapArena() {
+ return DEFAULT_NUM_HEAP_ARENA;
+ }
+
+ /**
+ * Default numer of direct arenas - System Property: io.netty.allocator.numDirectArenas - default 2 * cores
+ */
+ public static int defaultNumDirectArena() {
+ return DEFAULT_NUM_DIRECT_ARENA;
+ }
+
+ /**
+ * Default buffer page size - System Property: io.netty.allocator.pageSize - default 8192
+ */
+ public static int defaultPageSize() {
+ return DEFAULT_PAGE_SIZE;
+ }
+
+ /**
+ * Default maximum order - System Property: io.netty.allocator.maxOrder - default 11
+ */
+ public static int defaultMaxOrder() {
+ return DEFAULT_MAX_ORDER;
+ }
+
+ /**
+ * Default tiny cache size - System Property: io.netty.allocator.tinyCacheSize - default 512
+ */
+ public static int defaultTinyCacheSize() {
+ return DEFAULT_TINY_CACHE_SIZE;
+ }
+
+ /**
+ * Default small cache size - System Property: io.netty.allocator.smallCacheSize - default 256
+ */
+ public static int defaultSmallCacheSize() {
+ return DEFAULT_SMALL_CACHE_SIZE;
+ }
+
+ /**
+ * Default normal cache size - System Property: io.netty.allocator.normalCacheSize - default 64
+ */
+ public static int defaultNormalCacheSize() {
+ return DEFAULT_NORMAL_CACHE_SIZE;
+ }
+
@Override
public boolean isDirectBufferPooled() {
return directArenas != null;
diff -Nru netty-4.0.33/buffer/src/main/java/io/netty/buffer/SimpleLeakAwareCompositeByteBuf.java netty-4.0.34/buffer/src/main/java/io/netty/buffer/SimpleLeakAwareCompositeByteBuf.java
--- netty-4.0.33/buffer/src/main/java/io/netty/buffer/SimpleLeakAwareCompositeByteBuf.java 1970-01-01 00:00:00.000000000 +0000
+++ netty-4.0.34/buffer/src/main/java/io/netty/buffer/SimpleLeakAwareCompositeByteBuf.java 2016-01-29 08:23:46.000000000 +0000
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2016 The Netty Project
+ *
+ * The Netty Project licenses this file to you under the Apache License,
+ * version 2.0 (the "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+package io.netty.buffer;
+
+
+import io.netty.util.ResourceLeak;
+
+import java.nio.ByteOrder;
+
+final class SimpleLeakAwareCompositeByteBuf extends WrappedCompositeByteBuf {
+
+ private final ResourceLeak leak;
+
+ SimpleLeakAwareCompositeByteBuf(CompositeByteBuf wrapped, ResourceLeak leak) {
+ super(wrapped);
+ this.leak = leak;
+ }
+
+ @Override
+ public boolean release() {
+ boolean deallocated = super.release();
+ if (deallocated) {
+ leak.close();
+ }
+ return deallocated;
+ }
+
+ @Override
+ public boolean release(int decrement) {
+ boolean deallocated = super.release(decrement);
+ if (deallocated) {
+ leak.close();
+ }
+ return deallocated;
+ }
+
+ @Override
+ public ByteBuf order(ByteOrder endianness) {
+ leak.record();
+ if (order() == endianness) {
+ return this;
+ } else {
+ return new SimpleLeakAwareByteBuf(super.order(endianness), leak);
+ }
+ }
+
+ @Override
+ public ByteBuf slice() {
+ return new SimpleLeakAwareByteBuf(super.slice(), leak);
+ }
+
+ @Override
+ public ByteBuf slice(int index, int length) {
+ return new SimpleLeakAwareByteBuf(super.slice(index, length), leak);
+ }
+
+ @Override
+ public ByteBuf duplicate() {
+ return new SimpleLeakAwareByteBuf(super.duplicate(), leak);
+ }
+
+ @Override
+ public ByteBuf readSlice(int length) {
+ return new SimpleLeakAwareByteBuf(super.readSlice(length), leak);
+ }
+}
diff -Nru netty-4.0.33/buffer/src/main/java/io/netty/buffer/Unpooled.java netty-4.0.34/buffer/src/main/java/io/netty/buffer/Unpooled.java
--- netty-4.0.33/buffer/src/main/java/io/netty/buffer/Unpooled.java 2015-11-03 13:18:17.000000000 +0000
+++ netty-4.0.34/buffer/src/main/java/io/netty/buffer/Unpooled.java 2016-01-29 08:23:46.000000000 +0000
@@ -211,11 +211,15 @@
* Creates a new buffer which wraps the specified buffer's readable bytes.
* A modification on the specified buffer's content will be visible to the
* returned buffer.
+ * @param buffer The buffer to wrap. Reference count ownership of this variable is transfered to this method.
+ * @return The readable portion of the {@code buffer}, or an empty buffer if there is no readable portion.
+ * The caller is responsible for releasing this buffer.
*/
public static ByteBuf wrappedBuffer(ByteBuf buffer) {
if (buffer.isReadable()) {
return buffer.slice();
} else {
+ buffer.release();
return EMPTY_BUFFER;
}
}
@@ -226,16 +230,18 @@
* content will be visible to the returned buffer.
*/
public static ByteBuf wrappedBuffer(byte[]... arrays) {
- return wrappedBuffer(16, arrays);
+ return wrappedBuffer(AbstractByteBufAllocator.DEFAULT_MAX_COMPONENTS, arrays);
}
/**
* Creates a new big-endian composite buffer which wraps the readable bytes of the
* specified buffers without copying them. A modification on the content
* of the specified buffers will be visible to the returned buffer.
+ * @param buffers The buffers to wrap. Reference count ownership of all variables is transfered to this method.
+ * @return The readable portion of the {@code buffers}. The caller is responsible for releasing this buffer.
*/
public static ByteBuf wrappedBuffer(ByteBuf... buffers) {
- return wrappedBuffer(16, buffers);
+ return wrappedBuffer(AbstractByteBufAllocator.DEFAULT_MAX_COMPONENTS, buffers);
}
/**
@@ -244,7 +250,7 @@
* specified buffers will be visible to the returned buffer.
*/
public static ByteBuf wrappedBuffer(ByteBuffer... buffers) {
- return wrappedBuffer(16, buffers);
+ return wrappedBuffer(AbstractByteBufAllocator.DEFAULT_MAX_COMPONENTS, buffers);
}
/**
@@ -285,20 +291,29 @@
* Creates a new big-endian composite buffer which wraps the readable bytes of the
* specified buffers without copying them. A modification on the content
* of the specified buffers will be visible to the returned buffer.
+ * @param maxNumComponents Advisement as to how many independent buffers are allowed to exist before
+ * consolidation occurs.
+ * @param buffers The buffers to wrap. Reference count ownership of all variables is transfered to this method.
+ * @return The readable portion of the {@code buffers}. The caller is responsible for releasing this buffer.
*/
public static ByteBuf wrappedBuffer(int maxNumComponents, ByteBuf... buffers) {
switch (buffers.length) {
case 0:
break;
case 1:
- if (buffers[0].isReadable()) {
- return wrappedBuffer(buffers[0].order(BIG_ENDIAN));
+ ByteBuf buffer = buffers[0];
+ if (buffer.isReadable()) {
+ return wrappedBuffer(buffer.order(BIG_ENDIAN));
+ } else {
+ buffer.release();
}
break;
default:
for (ByteBuf b: buffers) {
if (b.isReadable()) {
return new CompositeByteBuf(ALLOC, false, maxNumComponents, buffers);
+ } else {
+ b.release();
}
}
}
@@ -343,7 +358,7 @@
* Returns a new big-endian composite buffer with no components.
*/
public static CompositeByteBuf compositeBuffer() {
- return compositeBuffer(16);
+ return compositeBuffer(AbstractByteBufAllocator.DEFAULT_MAX_COMPONENTS);
}
/**
diff -Nru netty-4.0.33/buffer/src/main/java/io/netty/buffer/UnsafeByteBufUtil.java netty-4.0.34/buffer/src/main/java/io/netty/buffer/UnsafeByteBufUtil.java
--- netty-4.0.33/buffer/src/main/java/io/netty/buffer/UnsafeByteBufUtil.java 2015-11-03 13:18:17.000000000 +0000
+++ netty-4.0.34/buffer/src/main/java/io/netty/buffer/UnsafeByteBufUtil.java 2016-01-29 08:23:46.000000000 +0000
@@ -22,6 +22,7 @@
import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
+import java.nio.ReadOnlyBufferException;
import static io.netty.util.internal.MathUtil.isOutOfBounds;
import static io.netty.util.internal.ObjectUtil.checkNotNull;
@@ -315,15 +316,21 @@
}
if (dst.isDirect()) {
+ if (dst.isReadOnly()) {
+ // We need to check if dst is ready-only so we not write something in it by using Unsafe.
+ throw new ReadOnlyBufferException();
+ }
// Copy to direct memory
long dstAddress = PlatformDependent.directBufferAddress(dst);
PlatformDependent.copyMemory(addr, dstAddress + dst.position(), bytesToCopy);
- } else {
+ dst.position(dst.position() + bytesToCopy);
+ } else if (dst.hasArray()) {
// Copy to array
PlatformDependent.copyMemory(addr, dst.array(), dst.arrayOffset() + dst.position(), bytesToCopy);
+ dst.position(dst.position() + bytesToCopy);
+ } else {
+ dst.put(buf.nioBuffer());
}
-
- dst.position(dst.position() + bytesToCopy);
}
static void setBytes(AbstractByteBuf buf, long addr, int index, ByteBuf src, int srcIndex, int length) {
@@ -363,11 +370,21 @@
// Copy from direct memory
long srcAddress = PlatformDependent.directBufferAddress(src);
PlatformDependent.copyMemory(srcAddress + src.position(), addr, src.remaining());
- } else {
+ src.position(src.position() + length);
+ } else if (src.hasArray()) {
// Copy from array
PlatformDependent.copyMemory(src.array(), src.arrayOffset() + src.position(), addr, length);
+ src.position(src.position() + length);
+ } else {
+ ByteBuf tmpBuf = buf.alloc().heapBuffer(length);
+ try {
+ byte[] tmp = tmpBuf.array();
+ src.get(tmp, tmpBuf.arrayOffset(), length); // moves the src position too
+ PlatformDependent.copyMemory(tmp, 0, addr, length);
+ } finally {
+ tmpBuf.release();
+ }
}
- src.position(src.position() + length);
}
static void getBytes(AbstractByteBuf buf, long addr, int index, OutputStream out, int length) throws IOException {
diff -Nru netty-4.0.33/buffer/src/main/java/io/netty/buffer/WrappedCompositeByteBuf.java netty-4.0.34/buffer/src/main/java/io/netty/buffer/WrappedCompositeByteBuf.java
--- netty-4.0.33/buffer/src/main/java/io/netty/buffer/WrappedCompositeByteBuf.java 1970-01-01 00:00:00.000000000 +0000
+++ netty-4.0.34/buffer/src/main/java/io/netty/buffer/WrappedCompositeByteBuf.java 2016-01-29 08:23:46.000000000 +0000
@@ -0,0 +1,994 @@
+/*
+ * Copyright 2016 The Netty Project
+ *
+ * The Netty Project licenses this file to you under the Apache License,
+ * version 2.0 (the "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+package io.netty.buffer;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.channels.GatheringByteChannel;
+import java.nio.channels.ScatteringByteChannel;
+import java.nio.charset.Charset;
+import java.util.Iterator;
+import java.util.List;
+
+class WrappedCompositeByteBuf extends CompositeByteBuf {
+
+ private final CompositeByteBuf wrapped;
+
+ WrappedCompositeByteBuf(CompositeByteBuf wrapped) {
+ super(wrapped.alloc());
+ this.wrapped = wrapped;
+ }
+
+ @Override
+ public boolean release() {
+ return wrapped.release();
+ }
+
+ @Override
+ public boolean release(int decrement) {
+ return wrapped.release(decrement);
+ }
+
+ @Override
+ public final int maxCapacity() {
+ return wrapped.maxCapacity();
+ }
+
+ @Override
+ public final int readerIndex() {
+ return wrapped.readerIndex();
+ }
+
+ @Override
+ public final int writerIndex() {
+ return wrapped.writerIndex();
+ }
+
+ @Override
+ public final boolean isReadable() {
+ return wrapped.isReadable();
+ }
+
+ @Override
+ public final boolean isReadable(int numBytes) {
+ return wrapped.isReadable(numBytes);
+ }
+
+ @Override
+ public final boolean isWritable() {
+ return wrapped.isWritable();
+ }
+
+ @Override
+ public final boolean isWritable(int numBytes) {
+ return wrapped.isWritable(numBytes);
+ }
+
+ @Override
+ public final int readableBytes() {
+ return wrapped.readableBytes();
+ }
+
+ @Override
+ public final int writableBytes() {
+ return wrapped.writableBytes();
+ }
+
+ @Override
+ public final int maxWritableBytes() {
+ return wrapped.maxWritableBytes();
+ }
+
+ @Override
+ public int ensureWritable(int minWritableBytes, boolean force) {
+ return wrapped.ensureWritable(minWritableBytes, force);
+ }
+
+ @Override
+ public ByteBuf order(ByteOrder endianness) {
+ return wrapped.order(endianness);
+ }
+
+ @Override
+ public boolean getBoolean(int index) {
+ return wrapped.getBoolean(index);
+ }
+
+ @Override
+ public short getUnsignedByte(int index) {
+ return wrapped.getUnsignedByte(index);
+ }
+
+ @Override
+ public short getShort(int index) {
+ return wrapped.getShort(index);
+ }
+
+ @Override
+ public int getUnsignedShort(int index) {
+ return wrapped.getUnsignedShort(index);
+ }
+
+ @Override
+ public int getUnsignedMedium(int index) {
+ return wrapped.getUnsignedMedium(index);
+ }
+
+ @Override
+ public int getMedium(int index) {
+ return wrapped.getMedium(index);
+ }
+
+ @Override
+ public int getInt(int index) {
+ return wrapped.getInt(index);
+ }
+
+ @Override
+ public long getUnsignedInt(int index) {
+ return wrapped.getUnsignedInt(index);
+ }
+
+ @Override
+ public long getLong(int index) {
+ return wrapped.getLong(index);
+ }
+
+ @Override
+ public char getChar(int index) {
+ return wrapped.getChar(index);
+ }
+
+ @Override
+ public float getFloat(int index) {
+ return wrapped.getFloat(index);
+ }
+
+ @Override
+ public double getDouble(int index) {
+ return wrapped.getDouble(index);
+ }
+
+ @Override
+ public byte readByte() {
+ return wrapped.readByte();
+ }
+
+ @Override
+ public boolean readBoolean() {
+ return wrapped.readBoolean();
+ }
+
+ @Override
+ public short readUnsignedByte() {
+ return wrapped.readUnsignedByte();
+ }
+
+ @Override
+ public short readShort() {
+ return wrapped.readShort();
+ }
+
+ @Override
+ public int readUnsignedShort() {
+ return wrapped.readUnsignedShort();
+ }
+
+ @Override
+ public int readMedium() {
+ return wrapped.readMedium();
+ }
+
+ @Override
+ public int readUnsignedMedium() {
+ return wrapped.readUnsignedMedium();
+ }
+
+ @Override
+ public int readInt() {
+ return wrapped.readInt();
+ }
+
+ @Override
+ public long readUnsignedInt() {
+ return wrapped.readUnsignedInt();
+ }
+
+ @Override
+ public long readLong() {
+ return wrapped.readLong();
+ }
+
+ @Override
+ public char readChar() {
+ return wrapped.readChar();
+ }
+
+ @Override
+ public float readFloat() {
+ return wrapped.readFloat();
+ }
+
+ @Override
+ public double readDouble() {
+ return wrapped.readDouble();
+ }
+
+ @Override
+ public ByteBuf readBytes(int length) {
+ return wrapped.readBytes(length);
+ }
+
+ @Override
+ public ByteBuf slice() {
+ return wrapped.slice();
+ }
+
+ @Override
+ public ByteBuf slice(int index, int length) {
+ return wrapped.slice(index, length);
+ }
+
+ @Override
+ public ByteBuffer nioBuffer() {
+ return wrapped.nioBuffer();
+ }
+
+ @Override
+ public String toString(Charset charset) {
+ return wrapped.toString(charset);
+ }
+
+ @Override
+ public String toString(int index, int length, Charset charset) {
+ return wrapped.toString(index, length, charset);
+ }
+
+ @Override
+ public int indexOf(int fromIndex, int toIndex, byte value) {
+ return wrapped.indexOf(fromIndex, toIndex, value);
+ }
+
+ @Override
+ public int bytesBefore(byte value) {
+ return wrapped.bytesBefore(value);
+ }
+
+ @Override
+ public int bytesBefore(int length, byte value) {
+ return wrapped.bytesBefore(length, value);
+ }
+
+ @Override
+ public int bytesBefore(int index, int length, byte value) {
+ return wrapped.bytesBefore(index, length, value);
+ }
+
+ @Override
+ public int forEachByte(ByteBufProcessor processor) {
+ return wrapped.forEachByte(processor);
+ }
+
+ @Override
+ public int forEachByte(int index, int length, ByteBufProcessor processor) {
+ return wrapped.forEachByte(index, length, processor);
+ }
+
+ @Override
+ public int forEachByteDesc(ByteBufProcessor processor) {
+ return wrapped.forEachByteDesc(processor);
+ }
+
+ @Override
+ public int forEachByteDesc(int index, int length, ByteBufProcessor processor) {
+ return wrapped.forEachByteDesc(index, length, processor);
+ }
+
+ @Override
+ public final int hashCode() {
+ return wrapped.hashCode();
+ }
+
+ @Override
+ public final boolean equals(Object o) {
+ return wrapped.equals(o);
+ }
+
+ @Override
+ public final int compareTo(ByteBuf that) {
+ return wrapped.compareTo(that);
+ }
+
+ @Override
+ public final int refCnt() {
+ return wrapped.refCnt();
+ }
+
+ @Override
+ public ByteBuf duplicate() {
+ return wrapped.duplicate();
+ }
+
+ @Override
+ public ByteBuf readSlice(int length) {
+ return wrapped.readSlice(length);
+ }
+
+ @Override
+ public int readBytes(GatheringByteChannel out, int length) throws IOException {
+ return wrapped.readBytes(out, length);
+ }
+
+ @Override
+ public int writeBytes(InputStream in, int length) throws IOException {
+ return wrapped.writeBytes(in, length);
+ }
+
+ @Override
+ public int writeBytes(ScatteringByteChannel in, int length) throws IOException {
+ return wrapped.writeBytes(in, length);
+ }
+
+ @Override
+ public ByteBuf copy() {
+ return wrapped.copy();
+ }
+
+ @Override
+ public CompositeByteBuf addComponent(ByteBuf buffer) {
+ wrapped.addComponent(buffer);
+ return this;
+ }
+
+ @Override
+ public CompositeByteBuf addComponents(ByteBuf... buffers) {
+ wrapped.addComponents(buffers);
+ return this;
+ }
+
+ @Override
+ public CompositeByteBuf addComponents(Iterable buffers) {
+ wrapped.addComponents(buffers);
+ return this;
+ }
+
+ @Override
+ public CompositeByteBuf addComponent(int cIndex, ByteBuf buffer) {
+ wrapped.addComponent(cIndex, buffer);
+ return this;
+ }
+
+ @Override
+ public CompositeByteBuf addComponents(int cIndex, ByteBuf... buffers) {
+ wrapped.addComponents(cIndex, buffers);
+ return this;
+ }
+
+ @Override
+ public CompositeByteBuf addComponents(int cIndex, Iterable buffers) {
+ wrapped.addComponents(cIndex, buffers);
+ return this;
+ }
+
+ @Override
+ public CompositeByteBuf removeComponent(int cIndex) {
+ wrapped.removeComponent(cIndex);
+ return this;
+ }
+
+ @Override
+ public CompositeByteBuf removeComponents(int cIndex, int numComponents) {
+ wrapped.removeComponents(cIndex, numComponents);
+ return this;
+ }
+
+ @Override
+ public Iterator iterator() {
+ return wrapped.iterator();
+ }
+
+ @Override
+ public List decompose(int offset, int length) {
+ return wrapped.decompose(offset, length);
+ }
+
+ @Override
+ public final boolean isDirect() {
+ return wrapped.isDirect();
+ }
+
+ @Override
+ public final boolean hasArray() {
+ return wrapped.hasArray();
+ }
+
+ @Override
+ public final byte[] array() {
+ return wrapped.array();
+ }
+
+ @Override
+ public final int arrayOffset() {
+ return wrapped.arrayOffset();
+ }
+
+ @Override
+ public final boolean hasMemoryAddress() {
+ return wrapped.hasMemoryAddress();
+ }
+
+ @Override
+ public final long memoryAddress() {
+ return wrapped.memoryAddress();
+ }
+
+ @Override
+ public final int capacity() {
+ return wrapped.capacity();
+ }
+
+ @Override
+ public CompositeByteBuf capacity(int newCapacity) {
+ wrapped.capacity(newCapacity);
+ return this;
+ }
+
+ @Override
+ public final ByteBufAllocator alloc() {
+ return wrapped.alloc();
+ }
+
+ @Override
+ public final ByteOrder order() {
+ return wrapped.order();
+ }
+
+ @Override
+ public final int numComponents() {
+ return wrapped.numComponents();
+ }
+
+ @Override
+ public final int maxNumComponents() {
+ return wrapped.maxNumComponents();
+ }
+
+ @Override
+ public final int toComponentIndex(int offset) {
+ return wrapped.toComponentIndex(offset);
+ }
+
+ @Override
+ public final int toByteIndex(int cIndex) {
+ return wrapped.toByteIndex(cIndex);
+ }
+
+ @Override
+ public byte getByte(int index) {
+ return wrapped.getByte(index);
+ }
+
+ @Override
+ protected final byte _getByte(int index) {
+ return wrapped._getByte(index);
+ }
+
+ @Override
+ protected final short _getShort(int index) {
+ return wrapped._getShort(index);
+ }
+
+ @Override
+ protected final int _getUnsignedMedium(int index) {
+ return wrapped._getUnsignedMedium(index);
+ }
+
+ @Override
+ protected final int _getInt(int index) {
+ return wrapped._getInt(index);
+ }
+
+ @Override
+ protected final long _getLong(int index) {
+ return wrapped._getLong(index);
+ }
+
+ @Override
+ public CompositeByteBuf getBytes(int index, byte[] dst, int dstIndex, int length) {
+ wrapped.getBytes(index, dst, dstIndex, length);
+ return this;
+ }
+
+ @Override
+ public CompositeByteBuf getBytes(int index, ByteBuffer dst) {
+ wrapped.getBytes(index, dst);
+ return this;
+ }
+
+ @Override
+ public CompositeByteBuf getBytes(int index, ByteBuf dst, int dstIndex, int length) {
+ wrapped.getBytes(index, dst, dstIndex, length);
+ return this;
+ }
+
+ @Override
+ public int getBytes(int index, GatheringByteChannel out, int length) throws IOException {
+ return wrapped.getBytes(index, out, length);
+ }
+
+ @Override
+ public CompositeByteBuf getBytes(int index, OutputStream out, int length) throws IOException {
+ wrapped.getBytes(index, out, length);
+ return this;
+ }
+
+ @Override
+ public CompositeByteBuf setByte(int index, int value) {
+ wrapped.setByte(index, value);
+ return this;
+ }
+
+ @Override
+ protected final void _setByte(int index, int value) {
+ wrapped._setByte(index, value);
+ }
+
+ @Override
+ public CompositeByteBuf setShort(int index, int value) {
+ wrapped.setShort(index, value);
+ return this;
+ }
+
+ @Override
+ protected final void _setShort(int index, int value) {
+ wrapped._setShort(index, value);
+ }
+
+ @Override
+ public CompositeByteBuf setMedium(int index, int value) {
+ wrapped.setMedium(index, value);
+ return this;
+ }
+
+ @Override
+ protected final void _setMedium(int index, int value) {
+ wrapped._setMedium(index, value);
+ }
+
+ @Override
+ public CompositeByteBuf setInt(int index, int value) {
+ wrapped.setInt(index, value);
+ return this;
+ }
+
+ @Override
+ protected final void _setInt(int index, int value) {
+ wrapped._setInt(index, value);
+ }
+
+ @Override
+ public CompositeByteBuf setLong(int index, long value) {
+ wrapped.setLong(index, value);
+ return this;
+ }
+
+ @Override
+ protected final void _setLong(int index, long value) {
+ wrapped._setLong(index, value);
+ }
+
+ @Override
+ public CompositeByteBuf setBytes(int index, byte[] src, int srcIndex, int length) {
+ wrapped.setBytes(index, src, srcIndex, length);
+ return this;
+ }
+
+ @Override
+ public CompositeByteBuf setBytes(int index, ByteBuffer src) {
+ wrapped.setBytes(index, src);
+ return this;
+ }
+
+ @Override
+ public CompositeByteBuf setBytes(int index, ByteBuf src, int srcIndex, int length) {
+ wrapped.setBytes(index, src, srcIndex, length);
+ return this;
+ }
+
+ @Override
+ public int setBytes(int index, InputStream in, int length) throws IOException {
+ return wrapped.setBytes(index, in, length);
+ }
+
+ @Override
+ public int setBytes(int index, ScatteringByteChannel in, int length) throws IOException {
+ return wrapped.setBytes(index, in, length);
+ }
+
+ @Override
+ public ByteBuf copy(int index, int length) {
+ return wrapped.copy(index, length);
+ }
+
+ @Override
+ public final ByteBuf component(int cIndex) {
+ return wrapped.component(cIndex);
+ }
+
+ @Override
+ public final ByteBuf componentAtOffset(int offset) {
+ return wrapped.componentAtOffset(offset);
+ }
+
+ @Override
+ public final ByteBuf internalComponent(int cIndex) {
+ return wrapped.internalComponent(cIndex);
+ }
+
+ @Override
+ public final ByteBuf internalComponentAtOffset(int offset) {
+ return wrapped.internalComponentAtOffset(offset);
+ }
+
+ @Override
+ public int nioBufferCount() {
+ return wrapped.nioBufferCount();
+ }
+
+ @Override
+ public ByteBuffer internalNioBuffer(int index, int length) {
+ return wrapped.internalNioBuffer(index, length);
+ }
+
+ @Override
+ public ByteBuffer nioBuffer(int index, int length) {
+ return wrapped.nioBuffer(index, length);
+ }
+
+ @Override
+ public ByteBuffer[] nioBuffers(int index, int length) {
+ return wrapped.nioBuffers(index, length);
+ }
+
+ @Override
+ public CompositeByteBuf consolidate() {
+ wrapped.consolidate();
+ return this;
+ }
+
+ @Override
+ public CompositeByteBuf consolidate(int cIndex, int numComponents) {
+ wrapped.consolidate(cIndex, numComponents);
+ return this;
+ }
+
+ @Override
+ public CompositeByteBuf discardReadComponents() {
+ wrapped.discardReadComponents();
+ return this;
+ }
+
+ @Override
+ public CompositeByteBuf discardReadBytes() {
+ wrapped.discardReadBytes();
+ return this;
+ }
+
+ @Override
+ public final String toString() {
+ return wrapped.toString();
+ }
+
+ @Override
+ public final CompositeByteBuf readerIndex(int readerIndex) {
+ wrapped.readerIndex(readerIndex);
+ return this;
+ }
+
+ @Override
+ public final CompositeByteBuf writerIndex(int writerIndex) {
+ wrapped.writerIndex(writerIndex);
+ return this;
+ }
+
+ @Override
+ public final CompositeByteBuf setIndex(int readerIndex, int writerIndex) {
+ wrapped.setIndex(readerIndex, writerIndex);
+ return this;
+ }
+
+ @Override
+ public final CompositeByteBuf clear() {
+ wrapped.clear();
+ return this;
+ }
+
+ @Override
+ public final CompositeByteBuf markReaderIndex() {
+ wrapped.markReaderIndex();
+ return this;
+ }
+
+ @Override
+ public final CompositeByteBuf resetReaderIndex() {
+ wrapped.resetReaderIndex();
+ return this;
+ }
+
+ @Override
+ public final CompositeByteBuf markWriterIndex() {
+ wrapped.markWriterIndex();
+ return this;
+ }
+
+ @Override
+ public final CompositeByteBuf resetWriterIndex() {
+ wrapped.resetWriterIndex();
+ return this;
+ }
+
+ @Override
+ public CompositeByteBuf ensureWritable(int minWritableBytes) {
+ wrapped.ensureWritable(minWritableBytes);
+ return this;
+ }
+
+ @Override
+ public CompositeByteBuf getBytes(int index, ByteBuf dst) {
+ wrapped.getBytes(index, dst);
+ return this;
+ }
+
+ @Override
+ public CompositeByteBuf getBytes(int index, ByteBuf dst, int length) {
+ wrapped.getBytes(index, dst, length);
+ return this;
+ }
+
+ @Override
+ public CompositeByteBuf getBytes(int index, byte[] dst) {
+ wrapped.getBytes(index, dst);
+ return this;
+ }
+
+ @Override
+ public CompositeByteBuf setBoolean(int index, boolean value) {
+ wrapped.setBoolean(index, value);
+ return this;
+ }
+
+ @Override
+ public CompositeByteBuf setChar(int index, int value) {
+ wrapped.setChar(index, value);
+ return this;
+ }
+
+ @Override
+ public CompositeByteBuf setFloat(int index, float value) {
+ wrapped.setFloat(index, value);
+ return this;
+ }
+
+ @Override
+ public CompositeByteBuf setDouble(int index, double value) {
+ wrapped.setDouble(index, value);
+ return this;
+ }
+
+ @Override
+ public CompositeByteBuf setBytes(int index, ByteBuf src) {
+ wrapped.setBytes(index, src);
+ return this;
+ }
+
+ @Override
+ public CompositeByteBuf setBytes(int index, ByteBuf src, int length) {
+ wrapped.setBytes(index, src, length);
+ return this;
+ }
+
+ @Override
+ public CompositeByteBuf setBytes(int index, byte[] src) {
+ wrapped.setBytes(index, src);
+ return this;
+ }
+
+ @Override
+ public CompositeByteBuf setZero(int index, int length) {
+ wrapped.setZero(index, length);
+ return this;
+ }
+
+ @Override
+ public CompositeByteBuf readBytes(ByteBuf dst) {
+ wrapped.readBytes(dst);
+ return this;
+ }
+
+ @Override
+ public CompositeByteBuf readBytes(ByteBuf dst, int length) {
+ wrapped.readBytes(dst, length);
+ return this;
+ }
+
+ @Override
+ public CompositeByteBuf readBytes(ByteBuf dst, int dstIndex, int length) {
+ wrapped.readBytes(dst, dstIndex, length);
+ return this;
+ }
+
+ @Override
+ public CompositeByteBuf readBytes(byte[] dst) {
+ wrapped.readBytes(dst);
+ return this;
+ }
+
+ @Override
+ public CompositeByteBuf readBytes(byte[] dst, int dstIndex, int length) {
+ wrapped.readBytes(dst, dstIndex, length);
+ return this;
+ }
+
+ @Override
+ public CompositeByteBuf readBytes(ByteBuffer dst) {
+ wrapped.readBytes(dst);
+ return this;
+ }
+
+ @Override
+ public CompositeByteBuf readBytes(OutputStream out, int length) throws IOException {
+ wrapped.readBytes(out, length);
+ return this;
+ }
+
+ @Override
+ public CompositeByteBuf skipBytes(int length) {
+ wrapped.skipBytes(length);
+ return this;
+ }
+
+ @Override
+ public CompositeByteBuf writeBoolean(boolean value) {
+ wrapped.writeBoolean(value);
+ return this;
+ }
+
+ @Override
+ public CompositeByteBuf writeByte(int value) {
+ wrapped.writeByte(value);
+ return this;
+ }
+
+ @Override
+ public CompositeByteBuf writeShort(int value) {
+ wrapped.writeShort(value);
+ return this;
+ }
+
+ @Override
+ public CompositeByteBuf writeMedium(int value) {
+ wrapped.writeMedium(value);
+ return this;
+ }
+
+ @Override
+ public CompositeByteBuf writeInt(int value) {
+ wrapped.writeInt(value);
+ return this;
+ }
+
+ @Override
+ public CompositeByteBuf writeLong(long value) {
+ wrapped.writeLong(value);
+ return this;
+ }
+
+ @Override
+ public CompositeByteBuf writeChar(int value) {
+ wrapped.writeChar(value);
+ return this;
+ }
+
+ @Override
+ public CompositeByteBuf writeFloat(float value) {
+ wrapped.writeFloat(value);
+ return this;
+ }
+
+ @Override
+ public CompositeByteBuf writeDouble(double value) {
+ wrapped.writeDouble(value);
+ return this;
+ }
+
+ @Override
+ public CompositeByteBuf writeBytes(ByteBuf src) {
+ wrapped.writeBytes(src);
+ return this;
+ }
+
+ @Override
+ public CompositeByteBuf writeBytes(ByteBuf src, int length) {
+ wrapped.writeBytes(src, length);
+ return this;
+ }
+
+ @Override
+ public CompositeByteBuf writeBytes(ByteBuf src, int srcIndex, int length) {
+ wrapped.writeBytes(src, srcIndex, length);
+ return this;
+ }
+
+ @Override
+ public CompositeByteBuf writeBytes(byte[] src) {
+ wrapped.writeBytes(src);
+ return this;
+ }
+
+ @Override
+ public CompositeByteBuf writeBytes(byte[] src, int srcIndex, int length) {
+ wrapped.writeBytes(src, srcIndex, length);
+ return this;
+ }
+
+ @Override
+ public CompositeByteBuf writeBytes(ByteBuffer src) {
+ wrapped.writeBytes(src);
+ return this;
+ }
+
+ @Override
+ public CompositeByteBuf writeZero(int length) {
+ wrapped.writeZero(length);
+ return this;
+ }
+
+ @Override
+ public CompositeByteBuf retain(int increment) {
+ wrapped.retain(increment);
+ return this;
+ }
+
+ @Override
+ public CompositeByteBuf retain() {
+ wrapped.retain();
+ return this;
+ }
+
+ @Override
+ public ByteBuffer[] nioBuffers() {
+ return wrapped.nioBuffers();
+ }
+
+ @Override
+ public CompositeByteBuf discardSomeReadBytes() {
+ wrapped.discardSomeReadBytes();
+ return this;
+ }
+
+ @Override
+ public final void deallocate() {
+ wrapped.deallocate();
+ }
+
+ @Override
+ public final ByteBuf unwrap() {
+ return wrapped;
+ }
+}
diff -Nru netty-4.0.33/buffer/src/test/java/io/netty/buffer/AbstractByteBufTest.java netty-4.0.34/buffer/src/test/java/io/netty/buffer/AbstractByteBufTest.java
--- netty-4.0.33/buffer/src/test/java/io/netty/buffer/AbstractByteBufTest.java 2015-11-03 13:18:17.000000000 +0000
+++ netty-4.0.34/buffer/src/test/java/io/netty/buffer/AbstractByteBufTest.java 2016-01-29 08:23:46.000000000 +0000
@@ -27,6 +27,7 @@
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
+import java.nio.ReadOnlyBufferException;
import java.nio.channels.Channels;
import java.nio.channels.GatheringByteChannel;
import java.nio.channels.ScatteringByteChannel;
@@ -2495,6 +2496,33 @@
assertFalse(nioBuffers[0].hasRemaining());
}
+ @Test
+ public void testGetReadOnlyDirectDst() {
+ testGetReadOnlyDst(true);
+ }
+
+ @Test
+ public void testGetReadOnlyHeapDst() {
+ testGetReadOnlyDst(false);
+ }
+
+ private void testGetReadOnlyDst(boolean direct) {
+ byte[] bytes = { 'a', 'b', 'c', 'd' };
+
+ ByteBuf buffer = releaseLater(newBuffer(bytes.length));
+ buffer.writeBytes(bytes);
+
+ ByteBuffer dst = direct ? ByteBuffer.allocateDirect(bytes.length) : ByteBuffer.allocate(bytes.length);
+ ByteBuffer readOnlyDst = dst.asReadOnlyBuffer();
+ try {
+ buffer.getBytes(0, readOnlyDst);
+ fail();
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ assertEquals(0, readOnlyDst.position());
+ }
+
private void testRefCnt0(final boolean parameter) throws Exception {
for (int i = 0; i < 10; i++) {
final CountDownLatch latch = new CountDownLatch(1);
diff -Nru netty-4.0.33/buffer/src/test/java/io/netty/buffer/ByteBufUtilTest.java netty-4.0.34/buffer/src/test/java/io/netty/buffer/ByteBufUtilTest.java
--- netty-4.0.33/buffer/src/test/java/io/netty/buffer/ByteBufUtilTest.java 2015-11-03 13:18:17.000000000 +0000
+++ netty-4.0.34/buffer/src/test/java/io/netty/buffer/ByteBufUtilTest.java 2016-01-29 08:23:46.000000000 +0000
@@ -60,6 +60,21 @@
}
@Test
+ public void testWriteUtf8Surrogates() {
+ // leading surrogate + trailing surrogate
+ String surrogateString = new StringBuilder(2)
+ .append('\uD800')
+ .append('\uDC00')
+ .toString();
+ ByteBuf buf = ReferenceCountUtil.releaseLater(Unpooled.buffer(16));
+ buf.writeBytes(surrogateString.getBytes(CharsetUtil.UTF_8));
+ ByteBuf buf2 = ReferenceCountUtil.releaseLater(Unpooled.buffer(16));
+ ByteBufUtil.writeUtf8(buf2, surrogateString);
+
+ Assert.assertEquals(buf, buf2);
+ }
+
+ @Test
public void testWriteUtf8Wrapped() {
String usAscii = "Some UTF-8 like äÄ∏ŒŒ";
ByteBuf buf = Unpooled.unreleasableBuffer(ReferenceCountUtil.releaseLater(Unpooled.buffer(16)));
@@ -91,4 +106,17 @@
Assert.assertEquals(text, ByteBufUtil.decodeString(buffer, 0, buffer.readableBytes(), charset));
buffer.release();
}
+
+ @Test
+ public void testToStringDoesNotThrowIndexOutOfBounds() {
+ CompositeByteBuf buffer = Unpooled.compositeBuffer();
+ try {
+ byte[] bytes = "1234".getBytes(CharsetUtil.UTF_8);
+ buffer.addComponent(Unpooled.buffer(bytes.length).writeBytes(bytes));
+ buffer.addComponent(Unpooled.buffer(bytes.length).writeBytes(bytes));
+ Assert.assertEquals("1234", buffer.toString(bytes.length, bytes.length, CharsetUtil.UTF_8));
+ } finally {
+ buffer.release();
+ }
+ }
}
diff -Nru netty-4.0.33/buffer/src/test/java/io/netty/buffer/SlicedByteBufTest.java netty-4.0.34/buffer/src/test/java/io/netty/buffer/SlicedByteBufTest.java
--- netty-4.0.33/buffer/src/test/java/io/netty/buffer/SlicedByteBufTest.java 2015-11-03 13:18:17.000000000 +0000
+++ netty-4.0.34/buffer/src/test/java/io/netty/buffer/SlicedByteBufTest.java 2016-01-29 08:23:46.000000000 +0000
@@ -102,6 +102,18 @@
super.testWriteZeroAfterRelease();
}
+ @Test(expected = IndexOutOfBoundsException.class)
+ @Override
+ public void testGetReadOnlyDirectDst() {
+ super.testGetReadOnlyDirectDst();
+ }
+
+ @Test(expected = IndexOutOfBoundsException.class)
+ @Override
+ public void testGetReadOnlyHeapDst() {
+ super.testGetReadOnlyHeapDst();
+ }
+
@Test
@Override
public void testLittleEndianWithExpand() {
diff -Nru netty-4.0.33/buffer/src/test/java/io/netty/buffer/UnpooledTest.java netty-4.0.34/buffer/src/test/java/io/netty/buffer/UnpooledTest.java
--- netty-4.0.33/buffer/src/test/java/io/netty/buffer/UnpooledTest.java 2015-11-03 13:18:17.000000000 +0000
+++ netty-4.0.34/buffer/src/test/java/io/netty/buffer/UnpooledTest.java 2016-01-29 08:23:46.000000000 +0000
@@ -284,6 +284,42 @@
}
@Test
+ public void testSingleWrappedByteBufReleased() {
+ ByteBuf buf = buffer(12).writeByte(0);
+ ByteBuf wrapped = wrappedBuffer(buf);
+ assertTrue(wrapped.release());
+ assertEquals(0, buf.refCnt());
+ }
+
+ @Test
+ public void testSingleUnReadableWrappedByteBufReleased() {
+ ByteBuf buf = buffer(12);
+ ByteBuf wrapped = wrappedBuffer(buf);
+ assertFalse(wrapped.release()); // EMPTY_BUFFER cannot be released
+ assertEquals(0, buf.refCnt());
+ }
+
+ @Test
+ public void testMultiByteBufReleased() {
+ ByteBuf buf1 = buffer(12).writeByte(0);
+ ByteBuf buf2 = buffer(12).writeByte(0);
+ ByteBuf wrapped = wrappedBuffer(16, buf1, buf2);
+ assertTrue(wrapped.release());
+ assertEquals(0, buf1.refCnt());
+ assertEquals(0, buf2.refCnt());
+ }
+
+ @Test
+ public void testMultiUnReadableByteBufReleased() {
+ ByteBuf buf1 = buffer(12);
+ ByteBuf buf2 = buffer(12);
+ ByteBuf wrapped = wrappedBuffer(16, buf1, buf2);
+ assertFalse(wrapped.release()); // EMPTY_BUFFER cannot be released
+ assertEquals(0, buf1.refCnt());
+ assertEquals(0, buf2.refCnt());
+ }
+
+ @Test
public void testCopiedBuffer() {
assertEquals(16, copiedBuffer(ByteBuffer.allocateDirect(16)).capacity());
diff -Nru netty-4.0.33/buffer/src/test/java/io/netty/buffer/UnsafeByteBufUtilTest.java netty-4.0.34/buffer/src/test/java/io/netty/buffer/UnsafeByteBufUtilTest.java
--- netty-4.0.33/buffer/src/test/java/io/netty/buffer/UnsafeByteBufUtilTest.java 1970-01-01 00:00:00.000000000 +0000
+++ netty-4.0.34/buffer/src/test/java/io/netty/buffer/UnsafeByteBufUtilTest.java 2016-01-29 08:23:46.000000000 +0000
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2015 The Netty Project
+ *
+ * The Netty Project licenses this file to you under the Apache License,
+ * version 2.0 (the "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+package io.netty.buffer;
+
+import org.junit.Test;
+
+import java.nio.ByteBuffer;
+
+import static io.netty.util.internal.PlatformDependent.directBufferAddress;
+import static org.junit.Assert.assertArrayEquals;
+
+public class UnsafeByteBufUtilTest {
+
+ @Test
+ public void testSetBytesOnReadOnlyByteBuffer() throws Exception {
+ byte[] testData = new byte[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
+ int length = testData.length;
+
+ ByteBuffer readOnlyBuffer = ByteBuffer.wrap(testData).asReadOnlyBuffer();
+
+ UnpooledByteBufAllocator alloc = new UnpooledByteBufAllocator(true);
+ UnpooledDirectByteBuf targetBuffer = new UnpooledDirectByteBuf(alloc, length, length);
+
+ try {
+ UnsafeByteBufUtil.setBytes(targetBuffer, directBufferAddress(targetBuffer.nioBuffer()), 0, readOnlyBuffer);
+
+ byte[] check = new byte[length];
+ targetBuffer.getBytes(0, check, 0, length);
+
+ assertArrayEquals("The byte array's copy does not equal the original", testData, check);
+ } finally {
+ targetBuffer.release();
+ }
+ }
+}
diff -Nru netty-4.0.33/codec/pom.xml netty-4.0.34/codec/pom.xml
--- netty-4.0.33/codec/pom.xml 2015-11-03 13:18:17.000000000 +0000
+++ netty-4.0.34/codec/pom.xml 2016-01-29 08:23:46.000000000 +0000
@@ -20,7 +20,7 @@
io.nettynetty-parent
- 4.0.33.Final
+ 4.0.34.Finalnetty-codec
diff -Nru netty-4.0.33/codec/src/main/java/io/netty/handler/codec/base64/Base64.java netty-4.0.34/codec/src/main/java/io/netty/handler/codec/base64/Base64.java
--- netty-4.0.33/codec/src/main/java/io/netty/handler/codec/base64/Base64.java 2015-11-03 13:18:17.000000000 +0000
+++ netty-4.0.34/codec/src/main/java/io/netty/handler/codec/base64/Base64.java 2016-01-29 08:23:46.000000000 +0000
@@ -20,7 +20,7 @@
package io.netty.handler.codec.base64;
import io.netty.buffer.ByteBuf;
-import io.netty.buffer.Unpooled;
+import io.netty.buffer.ByteBufAllocator;
/**
* Utility class for {@link ByteBuf} that encodes and decodes to and from
@@ -104,6 +104,11 @@
public static ByteBuf encode(
ByteBuf src, int off, int len, boolean breakLines, Base64Dialect dialect) {
+ return encode(src, off, len, breakLines, dialect, src.alloc());
+ }
+
+ public static ByteBuf encode(
+ ByteBuf src, int off, int len, boolean breakLines, Base64Dialect dialect, ByteBufAllocator allocator) {
if (src == null) {
throw new NullPointerException("src");
@@ -113,7 +118,7 @@
}
int len43 = len * 4 / 3;
- ByteBuf dest = Unpooled.buffer(
+ ByteBuf dest = allocator.buffer(
len43 +
(len % 3 > 0 ? 4 : 0) + // Account for padding
(breakLines ? len43 / MAX_LINE_LENGTH : 0)).order(src.order()); // New lines
@@ -121,11 +126,15 @@
int e = 0;
int len2 = len - 2;
int lineLength = 0;
- for (; d < len2; d += 3, e += 4) {
+ for (; d < len2; e += 4) {
encode3to4(src, d + off, 3, dest, e, dialect);
lineLength += 4;
- if (breakLines && lineLength == MAX_LINE_LENGTH) {
+ d += 3;
+
+ if (breakLines && lineLength == MAX_LINE_LENGTH
+ // Only add NEW_LINE if we not ended directly on the MAX_LINE_LENGTH
+ && d < len2) {
dest.setByte(e + 4, NEW_LINE);
e ++;
lineLength = 0;
@@ -206,6 +215,11 @@
public static ByteBuf decode(
ByteBuf src, int off, int len, Base64Dialect dialect) {
+ return decode(src, off, len, dialect, src.alloc());
+ }
+
+ public static ByteBuf decode(
+ ByteBuf src, int off, int len, Base64Dialect dialect, ByteBufAllocator allocator) {
if (src == null) {
throw new NullPointerException("src");
@@ -217,7 +231,7 @@
byte[] DECODABET = decodabet(dialect);
int len34 = len * 3 / 4;
- ByteBuf dest = src.alloc().buffer(len34).order(src.order()); // Upper limit on size of output
+ ByteBuf dest = allocator.buffer(len34).order(src.order()); // Upper limit on size of output
int outBuffPosn = 0;
byte[] b4 = new byte[4];
diff -Nru netty-4.0.33/codec/src/main/java/io/netty/handler/codec/ByteToMessageDecoder.java netty-4.0.34/codec/src/main/java/io/netty/handler/codec/ByteToMessageDecoder.java
--- netty-4.0.33/codec/src/main/java/io/netty/handler/codec/ByteToMessageDecoder.java 2015-11-03 13:18:17.000000000 +0000
+++ netty-4.0.34/codec/src/main/java/io/netty/handler/codec/ByteToMessageDecoder.java 2016-01-29 08:23:46.000000000 +0000
@@ -353,6 +353,15 @@
if (outSize > 0) {
fireChannelRead(ctx, out, outSize);
out.clear();
+
+ // Check if this handler was removed before continuing with decoding.
+ // If it was removed, it is not safe to continue to operate on the buffer.
+ //
+ // See:
+ // - https://github.com/netty/netty/issues/4635
+ if (ctx.isRemoved()) {
+ break;
+ }
outSize = 0;
}
diff -Nru netty-4.0.33/codec/src/main/java/io/netty/handler/codec/compression/JdkZlibEncoder.java netty-4.0.34/codec/src/main/java/io/netty/handler/codec/compression/JdkZlibEncoder.java
--- netty-4.0.33/codec/src/main/java/io/netty/handler/codec/compression/JdkZlibEncoder.java 2015-11-03 13:18:17.000000000 +0000
+++ netty-4.0.34/codec/src/main/java/io/netty/handler/codec/compression/JdkZlibEncoder.java 2016-01-29 08:23:46.000000000 +0000
@@ -22,6 +22,7 @@
import io.netty.channel.ChannelPromise;
import io.netty.channel.ChannelPromiseNotifier;
import io.netty.util.concurrent.EventExecutor;
+import io.netty.util.internal.OneTimeTask;
import java.util.concurrent.TimeUnit;
import java.util.zip.CRC32;
@@ -163,7 +164,7 @@
return finishEncode(ctx, promise);
} else {
final ChannelPromise p = ctx.newPromise();
- executor.execute(new Runnable() {
+ executor.execute(new OneTimeTask() {
@Override
public void run() {
ChannelFuture f = finishEncode(ctx(), p);
@@ -259,7 +260,7 @@
if (!f.isDone()) {
// Ensure the channel is closed even if the write operation completes in time.
- ctx.executor().schedule(new Runnable() {
+ ctx.executor().schedule(new OneTimeTask() {
@Override
public void run() {
ctx.close(promise);
diff -Nru netty-4.0.33/codec/src/main/java/io/netty/handler/codec/compression/JZlibEncoder.java netty-4.0.34/codec/src/main/java/io/netty/handler/codec/compression/JZlibEncoder.java
--- netty-4.0.33/codec/src/main/java/io/netty/handler/codec/compression/JZlibEncoder.java 2015-11-03 13:18:17.000000000 +0000
+++ netty-4.0.34/codec/src/main/java/io/netty/handler/codec/compression/JZlibEncoder.java 2016-01-29 08:23:46.000000000 +0000
@@ -26,6 +26,7 @@
import io.netty.channel.ChannelPromiseNotifier;
import io.netty.util.concurrent.EventExecutor;
import io.netty.util.internal.EmptyArrays;
+import io.netty.util.internal.OneTimeTask;
import java.util.concurrent.TimeUnit;
@@ -252,7 +253,7 @@
return finishEncode(ctx, promise);
} else {
final ChannelPromise p = ctx.newPromise();
- executor.execute(new Runnable() {
+ executor.execute(new OneTimeTask() {
@Override
public void run() {
ChannelFuture f = finishEncode(ctx(), p);
@@ -351,7 +352,7 @@
if (!f.isDone()) {
// Ensure the channel is closed even if the write operation completes in time.
- ctx.executor().schedule(new Runnable() {
+ ctx.executor().schedule(new OneTimeTask() {
@Override
public void run() {
ctx.close(promise);
diff -Nru netty-4.0.33/codec/src/main/java/io/netty/handler/codec/compression/Snappy.java netty-4.0.34/codec/src/main/java/io/netty/handler/codec/compression/Snappy.java
--- netty-4.0.33/codec/src/main/java/io/netty/handler/codec/compression/Snappy.java 2015-11-03 13:18:17.000000000 +0000
+++ netty-4.0.34/codec/src/main/java/io/netty/handler/codec/compression/Snappy.java 2016-01-29 08:23:46.000000000 +0000
@@ -229,7 +229,7 @@
* @param out The output buffer to copy to
* @param length The length of the literal to copy
*/
- private static void encodeLiteral(ByteBuf in, ByteBuf out, int length) {
+ static void encodeLiteral(ByteBuf in, ByteBuf out, int length) {
if (length < 61) {
out.writeByte(length - 1 << 2);
} else {
@@ -396,7 +396,7 @@
* @param out The output buffer to write the literal to
* @return The number of bytes appended to the output buffer, or -1 to indicate "try again later"
*/
- private static int decodeLiteral(byte tag, ByteBuf in, ByteBuf out) {
+ static int decodeLiteral(byte tag, ByteBuf in, ByteBuf out) {
in.markReaderIndex();
int length;
switch(tag >> 2 & 0x3F) {
@@ -418,7 +418,7 @@
}
length = ByteBufUtil.swapMedium(in.readUnsignedMedium());
break;
- case 64:
+ case 63:
if (in.readableBytes() < 4) {
return NOT_ENOUGH_INPUT;
}
diff -Nru netty-4.0.33/codec/src/main/java/io/netty/handler/codec/compression/ZlibCodecFactory.java netty-4.0.34/codec/src/main/java/io/netty/handler/codec/compression/ZlibCodecFactory.java
--- netty-4.0.33/codec/src/main/java/io/netty/handler/codec/compression/ZlibCodecFactory.java 2015-11-03 13:18:17.000000000 +0000
+++ netty-4.0.34/codec/src/main/java/io/netty/handler/codec/compression/ZlibCodecFactory.java 2016-01-29 08:23:46.000000000 +0000
@@ -33,7 +33,8 @@
private static final boolean noJdkZlibEncoder;
static {
- noJdkZlibDecoder = SystemPropertyUtil.getBoolean("io.netty.noJdkZlibDecoder", true);
+ noJdkZlibDecoder = SystemPropertyUtil.getBoolean("io.netty.noJdkZlibDecoder",
+ PlatformDependent.javaVersion() < 7);
logger.debug("-Dio.netty.noJdkZlibDecoder: {}", noJdkZlibDecoder);
noJdkZlibEncoder = SystemPropertyUtil.getBoolean("io.netty.noJdkZlibEncoder", false);
diff -Nru netty-4.0.33/codec/src/test/java/io/netty/handler/codec/base64/Base64Test.java netty-4.0.34/codec/src/test/java/io/netty/handler/codec/base64/Base64Test.java
--- netty-4.0.33/codec/src/test/java/io/netty/handler/codec/base64/Base64Test.java 1970-01-01 00:00:00.000000000 +0000
+++ netty-4.0.34/codec/src/test/java/io/netty/handler/codec/base64/Base64Test.java 2016-01-29 08:23:46.000000000 +0000
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2015 The Netty Project
+ *
+ * The Netty Project licenses this file to you under the Apache License,
+ * version 2.0 (the "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+package io.netty.handler.codec.base64;
+
+import io.netty.buffer.ByteBuf;
+import io.netty.util.CharsetUtil;
+import org.junit.Test;
+
+
+import static io.netty.buffer.Unpooled.copiedBuffer;
+import static org.junit.Assert.assertEquals;
+
+public class Base64Test {
+
+ @Test
+ public void testNotAddNewLineWhenEndOnLimit() {
+ ByteBuf src = copiedBuffer("abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcde",
+ CharsetUtil.US_ASCII);
+ ByteBuf expectedEncoded =
+ copiedBuffer("YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXphYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5emFiY2Rl",
+ CharsetUtil.US_ASCII);
+ testEncode(src, expectedEncoded);
+ }
+
+ @Test
+ public void testAddNewLine() {
+ ByteBuf src = copiedBuffer("abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz12345678",
+ CharsetUtil.US_ASCII);
+ ByteBuf expectedEncoded =
+ copiedBuffer("YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXphYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5ejEyMzQ1\nNjc4",
+ CharsetUtil.US_ASCII);
+ testEncode(src, expectedEncoded);
+ }
+
+ private static void testEncode(ByteBuf src, ByteBuf expectedEncoded) {
+ ByteBuf encoded = Base64.encode(src, true, Base64Dialect.STANDARD);
+ try {
+ assertEquals(expectedEncoded, encoded);
+ } finally {
+ src.release();
+ expectedEncoded.release();
+ encoded.release();
+ }
+ }
+}
diff -Nru netty-4.0.33/codec/src/test/java/io/netty/handler/codec/ByteToMessageDecoderTest.java netty-4.0.34/codec/src/test/java/io/netty/handler/codec/ByteToMessageDecoderTest.java
--- netty-4.0.33/codec/src/test/java/io/netty/handler/codec/ByteToMessageDecoderTest.java 2015-11-03 13:18:17.000000000 +0000
+++ netty-4.0.34/codec/src/test/java/io/netty/handler/codec/ByteToMessageDecoderTest.java 2016-01-29 08:23:46.000000000 +0000
@@ -21,13 +21,14 @@
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.embedded.EmbeddedChannel;
import io.netty.util.ReferenceCountUtil;
-import org.junit.Assert;
import org.junit.Test;
import java.util.List;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingDeque;
+import static org.junit.Assert.*;
+
public class ByteToMessageDecoderTest {
@Test
@@ -37,7 +38,7 @@
@Override
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List
*
* @param hostname the host name (optionally wildcard)
- * @param output the output value that will be returned by {@link #map(String)} when the specified host name
- * matches the specified input host name
+ * @param output the output value that will be returned by {@link #map(String)} when the specified host name
+ * matches the specified input host name
+ * @deprecated use {@link DomainMappingBuilder} to create and fill the mapping instead
*/
+ @Deprecated
public DomainNameMapping add(String hostname, V output) {
- if (hostname == null) {
- throw new NullPointerException("input");
- }
-
- if (output == null) {
- throw new NullPointerException("output");
- }
-
- map.put(normalizeHostname(hostname), output);
+ map.put(normalizeHostname(checkNotNull(hostname, "hostname")), checkNotNull(output, "output"));
return this;
}
/**
* Simple function to match DNS wildcard.
*/
- private static boolean matches(String hostNameTemplate, String hostName) {
- // note that inputs are converted and lowercased already
- if (DNS_WILDCARD_PATTERN.matcher(hostNameTemplate).matches()) {
- return hostNameTemplate.substring(2).equals(hostName) ||
- hostName.endsWith(hostNameTemplate.substring(1));
- } else {
- return hostNameTemplate.equals(hostName);
+ static boolean matches(String template, String hostName) {
+ if (template.startsWith("*.")) {
+ return template.regionMatches(2, hostName, 0, hostName.length())
+ || commonSuffixOfLength(hostName, template, template.length() - 1);
}
+ return template.equals(hostName);
}
/**
* IDNA ASCII conversion and case normalization
*/
- private static String normalizeHostname(String hostname) {
+ static String normalizeHostname(String hostname) {
if (needsNormalization(hostname)) {
hostname = IDN.toASCII(hostname, IDN.ALLOW_UNASSIGNED);
}
@@ -113,7 +109,7 @@
private static boolean needsNormalization(String hostname) {
final int length = hostname.length();
- for (int i = 0; i < length; i ++) {
+ for (int i = 0; i < length; i++) {
int c = hostname.charAt(i);
if (c > 0x7F) {
return true;
@@ -123,17 +119,16 @@
}
@Override
- public V map(String input) {
- if (input != null) {
- input = normalizeHostname(input);
+ public V map(String hostname) {
+ if (hostname != null) {
+ hostname = normalizeHostname(hostname);
for (Map.Entry entry : map.entrySet()) {
- if (matches(entry.getKey(), input)) {
+ if (matches(entry.getKey(), hostname)) {
return entry.getValue();
}
}
}
-
return defaultValue;
}
diff -Nru netty-4.0.33/common/src/main/java/io/netty/util/internal/MathUtil.java netty-4.0.34/common/src/main/java/io/netty/util/internal/MathUtil.java
--- netty-4.0.33/common/src/main/java/io/netty/util/internal/MathUtil.java 2015-11-03 13:18:17.000000000 +0000
+++ netty-4.0.34/common/src/main/java/io/netty/util/internal/MathUtil.java 2016-01-29 08:23:46.000000000 +0000
@@ -48,4 +48,19 @@
public static boolean isOutOfBounds(int index, int length, int capacity) {
return (index | length | (index + length) | (capacity - (index + length))) < 0;
}
+
+ /**
+ * Compare to {@code long} values.
+ * @param x the first {@code long} to compare.
+ * @param y the second {@code long} to compare.
+ * @return
+ *
+ *
0 if {@code x == y}
+ *
{@code > 0} if {@code x > y}
+ *
{@code < 0} if {@code x < y}
+ *
+ */
+ public static int compare(long x, long y) {
+ return (x < y) ? -1 : (x > y) ? 1 : 0;
+ }
}
diff -Nru netty-4.0.33/common/src/main/java/io/netty/util/internal/PlatformDependent0.java netty-4.0.34/common/src/main/java/io/netty/util/internal/PlatformDependent0.java
--- netty-4.0.33/common/src/main/java/io/netty/util/internal/PlatformDependent0.java 2015-11-03 13:18:17.000000000 +0000
+++ netty-4.0.34/common/src/main/java/io/netty/util/internal/PlatformDependent0.java 2016-01-29 08:23:46.000000000 +0000
@@ -269,17 +269,17 @@
}
static AtomicReferenceFieldUpdater newAtomicReferenceFieldUpdater(
- Class tclass, String fieldName) throws Exception {
+ Class super U> tclass, String fieldName) throws Exception {
return new UnsafeAtomicReferenceFieldUpdater(UNSAFE, tclass, fieldName);
}
static AtomicIntegerFieldUpdater newAtomicIntegerFieldUpdater(
- Class> tclass, String fieldName) throws Exception {
+ Class super T> tclass, String fieldName) throws Exception {
return new UnsafeAtomicIntegerFieldUpdater(UNSAFE, tclass, fieldName);
}
static AtomicLongFieldUpdater newAtomicLongFieldUpdater(
- Class> tclass, String fieldName) throws Exception {
+ Class super T> tclass, String fieldName) throws Exception {
return new UnsafeAtomicLongFieldUpdater(UNSAFE, tclass, fieldName);
}
diff -Nru netty-4.0.33/common/src/main/java/io/netty/util/internal/PlatformDependent.java netty-4.0.34/common/src/main/java/io/netty/util/internal/PlatformDependent.java
--- netty-4.0.33/common/src/main/java/io/netty/util/internal/PlatformDependent.java 2015-11-03 13:18:17.000000000 +0000
+++ netty-4.0.34/common/src/main/java/io/netty/util/internal/PlatformDependent.java 2016-01-29 08:23:46.000000000 +0000
@@ -88,7 +88,6 @@
private static final int BIT_MODE = bitMode0();
private static final int ADDRESS_SIZE = addressSize0();
- private static final boolean NATIVE_ORDER = ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN;
static {
if (logger.isDebugEnabled()) {
@@ -416,7 +415,7 @@
* use {@link AtomicReferenceFieldUpdater#newUpdater(Class, Class, String)} as fallback.
*/
public static AtomicReferenceFieldUpdater newAtomicReferenceFieldUpdater(
- Class tclass, String fieldName) {
+ Class super U> tclass, String fieldName) {
if (hasUnsafe()) {
try {
return PlatformDependent0.newAtomicReferenceFieldUpdater(tclass, fieldName);
@@ -433,7 +432,7 @@
* use {@link AtomicIntegerFieldUpdater#newUpdater(Class, String)} as fallback.
*/
public static AtomicIntegerFieldUpdater newAtomicIntegerFieldUpdater(
- Class> tclass, String fieldName) {
+ Class super T> tclass, String fieldName) {
if (hasUnsafe()) {
try {
return PlatformDependent0.newAtomicIntegerFieldUpdater(tclass, fieldName);
@@ -450,7 +449,7 @@
* use {@link AtomicLongFieldUpdater#newUpdater(Class, String)} as fallback.
*/
public static AtomicLongFieldUpdater newAtomicLongFieldUpdater(
- Class> tclass, String fieldName) {
+ Class super T> tclass, String fieldName) {
if (hasUnsafe()) {
try {
return PlatformDependent0.newAtomicLongFieldUpdater(tclass, fieldName);
@@ -518,7 +517,7 @@
try {
Class.forName("android.app.Application", false, getSystemClassLoader());
android = true;
- } catch (Exception e) {
+ } catch (Throwable ignored) {
// Failed to load the class uniquely available in Android.
android = false;
}
@@ -565,7 +564,7 @@
// Ignore
}
}
- } catch (Exception e) {
+ } catch (Throwable ignored) {
// Failed to run the command.
uid = null;
} finally {
@@ -646,7 +645,7 @@
Class.forName("java.time.Clock", false, getClassLoader(Object.class));
javaVersion = 8;
break;
- } catch (Exception e) {
+ } catch (Throwable ignored) {
// Ignore
}
@@ -654,7 +653,7 @@
Class.forName("java.util.concurrent.LinkedTransferQueue", false, getClassLoader(BlockingQueue.class));
javaVersion = 7;
break;
- } catch (Exception e) {
+ } catch (Throwable ignored) {
// Ignore
}
@@ -699,7 +698,7 @@
boolean hasUnsafe = PlatformDependent0.hasUnsafe();
logger.debug("sun.misc.Unsafe: {}", hasUnsafe ? "available" : "unavailable");
return hasUnsafe;
- } catch (Throwable t) {
+ } catch (Throwable ignored) {
// Probably failed to initialize PlatformDependent0.
return false;
}
@@ -720,7 +719,7 @@
Class> vmClass = Class.forName("sun.misc.VM", true, getSystemClassLoader());
Method m = vmClass.getDeclaredMethod("maxDirectMemory");
maxDirectMemory = ((Number) m.invoke(null)).longValue();
- } catch (Throwable t) {
+ } catch (Throwable ignored) {
// Ignore
}
@@ -760,7 +759,7 @@
}
break;
}
- } catch (Throwable t) {
+ } catch (Throwable ignored) {
// Ignore
}
@@ -845,7 +844,7 @@
return f;
}
}
- } catch (Exception ignored) {
+ } catch (Throwable ignored) {
// Environment variable inaccessible
}
diff -Nru netty-4.0.33/common/src/main/java/io/netty/util/internal/StringUtil.java netty-4.0.34/common/src/main/java/io/netty/util/internal/StringUtil.java
--- netty-4.0.33/common/src/main/java/io/netty/util/internal/StringUtil.java 2015-11-03 13:18:17.000000000 +0000
+++ netty-4.0.34/common/src/main/java/io/netty/util/internal/StringUtil.java 2016-01-29 08:23:46.000000000 +0000
@@ -184,6 +184,18 @@
}
/**
+ * Checks if two strings have the same suffix of specified length
+ *
+ * @param s string
+ * @param p string
+ * @param len length of the common suffix
+ * @return true if both s and p are not null and both have the same suffix. Otherwise - false
+ */
+ public static boolean commonSuffixOfLength(String s, String p, int len) {
+ return s != null && p != null && len >= 0 && s.regionMatches(s.length() - len, p, p.length() - len, len);
+ }
+
+ /**
* Converts the specified byte value into a 2-digit hexadecimal integer.
*/
public static String byteToHexStringPadded(int value) {
@@ -387,6 +399,17 @@
return s == null || s.isEmpty();
}
+ /**
+ * Determine if {@code c} lies within the range of values defined for
+ * Surrogate Code Point.
+ * @param c the character to check.
+ * @return {@code true} if {@code c} lies within the range of values defined for
+ * Surrogate Code Point. {@code false} otherwise.
+ */
+ public static boolean isSurrogate(char c) {
+ return c >= '\uD800' && c <= '\uDFFF';
+ }
+
private static boolean isDoubleQuote(char c) {
return c == DOUBLE_QUOTE;
}
diff -Nru netty-4.0.33/common/src/main/java/io/netty/util/internal/UnsafeAtomicIntegerFieldUpdater.java netty-4.0.34/common/src/main/java/io/netty/util/internal/UnsafeAtomicIntegerFieldUpdater.java
--- netty-4.0.33/common/src/main/java/io/netty/util/internal/UnsafeAtomicIntegerFieldUpdater.java 2015-11-03 13:18:17.000000000 +0000
+++ netty-4.0.34/common/src/main/java/io/netty/util/internal/UnsafeAtomicIntegerFieldUpdater.java 2016-01-29 08:23:46.000000000 +0000
@@ -25,7 +25,8 @@
private final long offset;
private final Unsafe unsafe;
- UnsafeAtomicIntegerFieldUpdater(Unsafe unsafe, Class> tClass, String fieldName) throws NoSuchFieldException {
+ UnsafeAtomicIntegerFieldUpdater(Unsafe unsafe, Class super T> tClass, String fieldName)
+ throws NoSuchFieldException {
Field field = tClass.getDeclaredField(fieldName);
if (!Modifier.isVolatile(field.getModifiers())) {
throw new IllegalArgumentException("Must be volatile");
diff -Nru netty-4.0.33/common/src/main/java/io/netty/util/internal/UnsafeAtomicLongFieldUpdater.java netty-4.0.34/common/src/main/java/io/netty/util/internal/UnsafeAtomicLongFieldUpdater.java
--- netty-4.0.33/common/src/main/java/io/netty/util/internal/UnsafeAtomicLongFieldUpdater.java 2015-11-03 13:18:17.000000000 +0000
+++ netty-4.0.34/common/src/main/java/io/netty/util/internal/UnsafeAtomicLongFieldUpdater.java 2016-01-29 08:23:46.000000000 +0000
@@ -25,7 +25,8 @@
private final long offset;
private final Unsafe unsafe;
- UnsafeAtomicLongFieldUpdater(Unsafe unsafe, Class> tClass, String fieldName) throws NoSuchFieldException {
+ UnsafeAtomicLongFieldUpdater(Unsafe unsafe, Class super T> tClass, String fieldName)
+ throws NoSuchFieldException {
Field field = tClass.getDeclaredField(fieldName);
if (!Modifier.isVolatile(field.getModifiers())) {
throw new IllegalArgumentException("Must be volatile");
diff -Nru netty-4.0.33/common/src/main/java/io/netty/util/internal/UnsafeAtomicReferenceFieldUpdater.java netty-4.0.34/common/src/main/java/io/netty/util/internal/UnsafeAtomicReferenceFieldUpdater.java
--- netty-4.0.33/common/src/main/java/io/netty/util/internal/UnsafeAtomicReferenceFieldUpdater.java 2015-11-03 13:18:17.000000000 +0000
+++ netty-4.0.34/common/src/main/java/io/netty/util/internal/UnsafeAtomicReferenceFieldUpdater.java 2016-01-29 08:23:46.000000000 +0000
@@ -25,7 +25,8 @@
private final long offset;
private final Unsafe unsafe;
- UnsafeAtomicReferenceFieldUpdater(Unsafe unsafe, Class tClass, String fieldName) throws NoSuchFieldException {
+ UnsafeAtomicReferenceFieldUpdater(Unsafe unsafe, Class super U> tClass, String fieldName)
+ throws NoSuchFieldException {
Field field = tClass.getDeclaredField(fieldName);
if (!Modifier.isVolatile(field.getModifiers())) {
throw new IllegalArgumentException("Must be volatile");
diff -Nru netty-4.0.33/common/src/main/java/io/netty/util/ThreadDeathWatcher.java netty-4.0.34/common/src/main/java/io/netty/util/ThreadDeathWatcher.java
--- netty-4.0.33/common/src/main/java/io/netty/util/ThreadDeathWatcher.java 2015-11-03 13:18:17.000000000 +0000
+++ netty-4.0.34/common/src/main/java/io/netty/util/ThreadDeathWatcher.java 2016-01-29 08:23:46.000000000 +0000
@@ -19,6 +19,8 @@
import io.netty.util.concurrent.DefaultThreadFactory;
import io.netty.util.internal.MpscLinkedQueueNode;
import io.netty.util.internal.PlatformDependent;
+import io.netty.util.internal.StringUtil;
+import io.netty.util.internal.SystemPropertyUtil;
import io.netty.util.internal.logging.InternalLogger;
import io.netty.util.internal.logging.InternalLoggerFactory;
@@ -40,14 +42,22 @@
public final class ThreadDeathWatcher {
private static final InternalLogger logger = InternalLoggerFactory.getInstance(ThreadDeathWatcher.class);
- private static final ThreadFactory threadFactory =
- new DefaultThreadFactory(ThreadDeathWatcher.class, true, Thread.MIN_PRIORITY);
+ private static final ThreadFactory threadFactory;
private static final Queue pendingEntries = PlatformDependent.newMpscQueue();
private static final Watcher watcher = new Watcher();
private static final AtomicBoolean started = new AtomicBoolean();
private static volatile Thread watcherThread;
+ static {
+ String poolName = "threadDeathWatcher";
+ String serviceThreadPrefix = SystemPropertyUtil.get("io.netty.serviceThreadPrefix");
+ if (!StringUtil.isNullOrEmpty(serviceThreadPrefix)) {
+ poolName = serviceThreadPrefix + poolName;
+ }
+ threadFactory = new DefaultThreadFactory(poolName, true, Thread.MIN_PRIORITY);
+ }
+
/**
* Schedules the specified {@code task} to run when the specified {@code thread} dies.
*
diff -Nru netty-4.0.33/common/src/test/java/io/netty/util/concurrent/DefaultPromiseTest.java netty-4.0.34/common/src/test/java/io/netty/util/concurrent/DefaultPromiseTest.java
--- netty-4.0.33/common/src/test/java/io/netty/util/concurrent/DefaultPromiseTest.java 2015-11-03 13:18:17.000000000 +0000
+++ netty-4.0.34/common/src/test/java/io/netty/util/concurrent/DefaultPromiseTest.java 2016-01-29 08:23:46.000000000 +0000
@@ -19,17 +19,39 @@
import org.junit.Test;
import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.CancellationException;
import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+import java.util.concurrent.atomic.AtomicInteger;
-import static org.hamcrest.CoreMatchers.*;
-import static org.junit.Assert.*;
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
@SuppressWarnings("unchecked")
public class DefaultPromiseTest {
+ @Test(expected = CancellationException.class)
+ public void testCancellationExceptionIsThrownWhenBlockingGet() throws InterruptedException, ExecutionException {
+ final Promise promise = new DefaultPromise(ImmediateEventExecutor.INSTANCE);
+ promise.cancel(false);
+ promise.get();
+ }
+
+ @Test(expected = CancellationException.class)
+ public void testCancellationExceptionIsThrownWhenBlockingGetWithTimeout() throws InterruptedException,
+ ExecutionException, TimeoutException {
+ final Promise promise = new DefaultPromise(ImmediateEventExecutor.INSTANCE);
+ promise.cancel(false);
+ promise.get(1, TimeUnit.SECONDS);
+ }
+
@Test
public void testNoStackOverflowErrorWithImmediateEventExecutorA() throws Exception {
final Promise[] p = new DefaultPromise[128];
@@ -84,54 +106,56 @@
@Test
public void testListenerNotifyOrder() throws Exception {
EventExecutor executor = new TestEventExecutor();
- final BlockingQueue> listeners = new LinkedBlockingQueue>();
- int runs = 100000;
-
- for (int i = 0; i < runs; i++) {
- final Promise promise = new DefaultPromise(executor);
- final FutureListener listener1 = new FutureListener() {
- @Override
- public void operationComplete(Future future) throws Exception {
- listeners.add(this);
- }
- };
- final FutureListener listener2 = new FutureListener() {
- @Override
- public void operationComplete(Future future) throws Exception {
- listeners.add(this);
- }
- };
- final FutureListener listener4 = new FutureListener() {
- @Override
- public void operationComplete(Future future) throws Exception {
- listeners.add(this);
- }
- };
- final FutureListener listener3 = new FutureListener() {
- @Override
- public void operationComplete(Future future) throws Exception {
- // Ensure listener4 is notified *after* this method returns to maintain the order.
- future.addListener(listener4);
- listeners.add(this);
- }
- };
+ try {
+ final BlockingQueue> listeners = new LinkedBlockingQueue>();
+ int runs = 100000;
+
+ for (int i = 0; i < runs; i++) {
+ final Promise promise = new DefaultPromise(executor);
+ final FutureListener listener1 = new FutureListener() {
+ @Override
+ public void operationComplete(Future future) throws Exception {
+ listeners.add(this);
+ }
+ };
+ final FutureListener listener2 = new FutureListener() {
+ @Override
+ public void operationComplete(Future future) throws Exception {
+ listeners.add(this);
+ }
+ };
+ final FutureListener listener4 = new FutureListener() {
+ @Override
+ public void operationComplete(Future future) throws Exception {
+ listeners.add(this);
+ }
+ };
+ final FutureListener listener3 = new FutureListener() {
+ @Override
+ public void operationComplete(Future future) throws Exception {
+ listeners.add(this);
+ future.addListener(listener4);
+ }
+ };
- GlobalEventExecutor.INSTANCE.execute(new Runnable() {
- @Override
- public void run() {
- promise.setSuccess(null);
- }
- });
+ GlobalEventExecutor.INSTANCE.execute(new Runnable() {
+ @Override
+ public void run() {
+ promise.setSuccess(null);
+ }
+ });
- promise.addListener(listener1).addListener(listener2).addListener(listener3);
+ promise.addListener(listener1).addListener(listener2).addListener(listener3);
- assertSame("Fail during run " + i + " / " + runs, listener1, listeners.take());
- assertSame("Fail during run " + i + " / " + runs, listener2, listeners.take());
- assertSame("Fail during run " + i + " / " + runs, listener3, listeners.take());
- assertSame("Fail during run " + i + " / " + runs, listener4, listeners.take());
- assertTrue("Fail during run " + i + " / " + runs, listeners.isEmpty());
+ assertSame("Fail 1 during run " + i + " / " + runs, listener1, listeners.take());
+ assertSame("Fail 2 during run " + i + " / " + runs, listener2, listeners.take());
+ assertSame("Fail 3 during run " + i + " / " + runs, listener3, listeners.take());
+ assertSame("Fail 4 during run " + i + " / " + runs, listener4, listeners.take());
+ assertTrue("Fail during run " + i + " / " + runs, listeners.isEmpty());
+ }
+ } finally {
+ executor.shutdownGracefully(0, 0, TimeUnit.SECONDS).sync();
}
- executor.shutdownGracefully().sync();
}
@Test
@@ -145,7 +169,7 @@
@Test(timeout = 2000)
public void testPromiseListenerAddWhenCompleteFailure() throws Exception {
- testPromiseListenerAddWhenComplete(new RuntimeException());
+ testPromiseListenerAddWhenComplete(fakeException());
}
@Test(timeout = 2000)
@@ -153,6 +177,93 @@
testPromiseListenerAddWhenComplete(null);
}
+ @Test(timeout = 2000)
+ public void testLateListenerIsOrderedCorrectlySuccess() throws InterruptedException {
+ testLateListenerIsOrderedCorrectly(null);
+ }
+
+ @Test(timeout = 2000)
+ public void testLateListenerIsOrderedCorrectlyFailure() throws InterruptedException {
+ testLateListenerIsOrderedCorrectly(fakeException());
+ }
+
+ /**
+ * This test is mean to simulate the following sequence of events, which all take place on the I/O thread:
+ *
+ *
A write is done
+ *
The write operation completes, and the promise state is changed to done
+ *
A listener is added to the return from the write. The {@link FutureListener#operationComplete()} updates
+ * state which must be invoked before the response to the previous write is read.
+ *
The write operation
+ *
+ */
+ private static void testLateListenerIsOrderedCorrectly(Throwable cause) throws InterruptedException {
+ final EventExecutor executor = new TestEventExecutor();
+ try {
+ final AtomicInteger state = new AtomicInteger();
+ final CountDownLatch latch1 = new CountDownLatch(1);
+ final CountDownLatch latch2 = new CountDownLatch(2);
+ final Promise promise = new DefaultPromise(executor);
+
+ // Add a listener before completion so "lateListener" is used next time we add a listener.
+ promise.addListener(new FutureListener() {
+ @Override
+ public void operationComplete(Future future) throws Exception {
+ assertTrue(state.compareAndSet(0, 1));
+ }
+ });
+
+ // Simulate write operation completing, which will execute listeners in another thread.
+ if (cause == null) {
+ promise.setSuccess(null);
+ } else {
+ promise.setFailure(cause);
+ }
+
+ // Add a "late listener"
+ promise.addListener(new FutureListener() {
+ @Override
+ public void operationComplete(Future future) throws Exception {
+ assertTrue(state.compareAndSet(1, 2));
+ latch1.countDown();
+ }
+ });
+
+ // Wait for the listeners and late listeners to be completed.
+ latch1.await();
+ assertEquals(2, state.get());
+
+ // This is the important listener. A late listener that is added after all late listeners
+ // have completed, and needs to update state before a read operation (on the same executor).
+ executor.execute(new Runnable() {
+ @Override
+ public void run() {
+ promise.addListener(new FutureListener() {
+ @Override
+ public void operationComplete(Future future) throws Exception {
+ assertTrue(state.compareAndSet(2, 3));
+ latch2.countDown();
+ }
+ });
+ }
+ });
+
+ // Simulate a read operation being queued up in the executor.
+ executor.execute(new Runnable() {
+ @Override
+ public void run() {
+ // This is the key, we depend upon the state being set in the next listener.
+ assertEquals(3, state.get());
+ latch2.countDown();
+ }
+ });
+
+ latch2.await();
+ } finally {
+ executor.shutdownGracefully(0, 0, TimeUnit.SECONDS).sync();
+ }
+ }
+
private static void testPromiseListenerAddWhenComplete(Throwable cause) throws InterruptedException {
final CountDownLatch latch = new CountDownLatch(1);
final Promise promise = new DefaultPromise(ImmediateEventExecutor.INSTANCE);
@@ -228,4 +339,8 @@
}
}
}
+
+ private static RuntimeException fakeException() {
+ return new RuntimeException("fake exception");
+ }
}
diff -Nru netty-4.0.33/common/src/test/java/io/netty/util/DomainNameMappingTest.java netty-4.0.34/common/src/test/java/io/netty/util/DomainNameMappingTest.java
--- netty-4.0.33/common/src/test/java/io/netty/util/DomainNameMappingTest.java 1970-01-01 00:00:00.000000000 +0000
+++ netty-4.0.34/common/src/test/java/io/netty/util/DomainNameMappingTest.java 2016-01-29 08:23:46.000000000 +0000
@@ -0,0 +1,184 @@
+/*
+* Copyright 2015 The Netty Project
+*
+* The Netty Project licenses this file to you under the Apache License,
+* version 2.0 (the "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at:
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+* License for the specific language governing permissions and limitations
+* under the License.
+*/
+
+package io.netty.util;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+@SuppressWarnings("deprecation")
+public class DomainNameMappingTest {
+
+ // Deprecated API
+
+ @Test(expected = NullPointerException.class)
+ public void testNullDefaultValueInDeprecatedApi() {
+ new DomainNameMapping(null);
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void testNullDomainNamePatternsAreForbiddenInDeprecatedApi() {
+ new DomainNameMapping("NotFound").add(null, "Some value");
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void testNullValuesAreForbiddenInDeprecatedApi() {
+ new DomainNameMapping("NotFound").add("Some key", null);
+ }
+
+ @Test
+ public void testDefaultValueInDeprecatedApi() {
+ DomainNameMapping mapping = new DomainNameMapping("NotFound");
+
+ assertEquals("NotFound", mapping.map("not-existing"));
+
+ mapping.add("*.netty.io", "Netty");
+
+ assertEquals("NotFound", mapping.map("not-existing"));
+ }
+
+ @Test
+ public void testStrictEqualityInDeprecatedApi() {
+ DomainNameMapping mapping = new DomainNameMapping("NotFound")
+ .add("netty.io", "Netty")
+ .add("downloads.netty.io", "Netty-Downloads");
+
+ assertEquals("Netty", mapping.map("netty.io"));
+ assertEquals("Netty-Downloads", mapping.map("downloads.netty.io"));
+
+ assertEquals("NotFound", mapping.map("x.y.z.netty.io"));
+ }
+
+ @Test
+ public void testWildcardMatchesAnyPrefixInDeprecatedApi() {
+ DomainNameMapping mapping = new DomainNameMapping("NotFound")
+ .add("*.netty.io", "Netty");
+
+ assertEquals("Netty", mapping.map("netty.io"));
+ assertEquals("Netty", mapping.map("downloads.netty.io"));
+ assertEquals("Netty", mapping.map("x.y.z.netty.io"));
+
+ assertEquals("NotFound", mapping.map("netty.io.x"));
+ }
+
+ @Test
+ public void testFirstMatchWinsInDeprecatedApi() {
+ assertEquals("Netty",
+ new DomainNameMapping("NotFound")
+ .add("*.netty.io", "Netty")
+ .add("downloads.netty.io", "Netty-Downloads")
+ .map("downloads.netty.io"));
+
+ assertEquals("Netty-Downloads",
+ new DomainNameMapping("NotFound")
+ .add("downloads.netty.io", "Netty-Downloads")
+ .add("*.netty.io", "Netty")
+ .map("downloads.netty.io"));
+ }
+
+ @Test
+ public void testToStringInDeprecatedApi() {
+ DomainNameMapping mapping = new DomainNameMapping("NotFound")
+ .add("*.netty.io", "Netty")
+ .add("downloads.netty.io", "Netty-Downloads");
+
+ assertEquals(
+ "DomainNameMapping(default: NotFound, map: {*.netty.io=Netty, downloads.netty.io=Netty-Downloads})",
+ mapping.toString());
+ }
+
+ // Immutable DomainNameMapping Builder API
+
+ @Test(expected = NullPointerException.class)
+ public void testNullDefaultValue() {
+ new DomainMappingBuilder(null);
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void testNullDomainNamePatternsAreForbidden() {
+ new DomainMappingBuilder("NotFound").add(null, "Some value");
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void testNullValuesAreForbidden() {
+ new DomainMappingBuilder("NotFound").add("Some key", null);
+ }
+
+ @Test
+ public void testDefaultValue() {
+ DomainNameMapping mapping = new DomainMappingBuilder("NotFound")
+ .add("*.netty.io", "Netty")
+ .build();
+
+ assertEquals("NotFound", mapping.map("not-existing"));
+ }
+
+ @Test
+ public void testStrictEquality() {
+ DomainNameMapping mapping = new DomainMappingBuilder("NotFound")
+ .add("netty.io", "Netty")
+ .add("downloads.netty.io", "Netty-Downloads")
+ .build();
+
+ assertEquals("Netty", mapping.map("netty.io"));
+ assertEquals("Netty-Downloads", mapping.map("downloads.netty.io"));
+
+ assertEquals("NotFound", mapping.map("x.y.z.netty.io"));
+ }
+
+ @Test
+ public void testWildcardMatchesAnyPrefix() {
+ DomainNameMapping mapping = new DomainMappingBuilder("NotFound")
+ .add("*.netty.io", "Netty")
+ .build();
+
+ assertEquals("Netty", mapping.map("netty.io"));
+ assertEquals("Netty", mapping.map("downloads.netty.io"));
+ assertEquals("Netty", mapping.map("x.y.z.netty.io"));
+
+ assertEquals("NotFound", mapping.map("netty.io.x"));
+ }
+
+ @Test
+ public void testFirstMatchWins() {
+ assertEquals("Netty",
+ new DomainMappingBuilder("NotFound")
+ .add("*.netty.io", "Netty")
+ .add("downloads.netty.io", "Netty-Downloads")
+ .build()
+ .map("downloads.netty.io"));
+
+ assertEquals("Netty-Downloads",
+ new DomainMappingBuilder("NotFound")
+ .add("downloads.netty.io", "Netty-Downloads")
+ .add("*.netty.io", "Netty")
+ .build()
+ .map("downloads.netty.io"));
+ }
+
+ @Test
+ public void testToString() {
+ DomainNameMapping mapping = new DomainMappingBuilder("NotFound")
+ .add("*.netty.io", "Netty")
+ .add("downloads.netty.io", "Netty-Download")
+ .build();
+
+ assertEquals(
+ "ImmutableDomainNameMapping(default: NotFound, map: {*.netty.io=Netty, downloads.netty.io=Netty-Download})",
+ mapping.toString());
+ }
+}
diff -Nru netty-4.0.33/common/src/test/java/io/netty/util/internal/StringUtilTest.java netty-4.0.34/common/src/test/java/io/netty/util/internal/StringUtilTest.java
--- netty-4.0.33/common/src/test/java/io/netty/util/internal/StringUtilTest.java 2015-11-03 13:18:17.000000000 +0000
+++ netty-4.0.34/common/src/test/java/io/netty/util/internal/StringUtilTest.java 2016-01-29 08:23:46.000000000 +0000
@@ -83,6 +83,245 @@
}
@Test
+ public void commonSuffixOfLengthTest() {
+ // negative length suffixes are never common
+ checkNotCommonSuffix("abc", "abc", -1);
+
+ // null has no suffix
+ checkNotCommonSuffix("abc", null, 0);
+ checkNotCommonSuffix(null, null, 0);
+
+ // any non-null string has 0-length suffix
+ checkCommonSuffix("abc", "xx", 0);
+
+ checkCommonSuffix("abc", "abc", 0);
+ checkCommonSuffix("abc", "abc", 1);
+ checkCommonSuffix("abc", "abc", 2);
+ checkCommonSuffix("abc", "abc", 3);
+ checkNotCommonSuffix("abc", "abc", 4);
+
+ checkCommonSuffix("abcd", "cd", 1);
+ checkCommonSuffix("abcd", "cd", 2);
+ checkNotCommonSuffix("abcd", "cd", 3);
+
+ checkCommonSuffix("abcd", "axcd", 1);
+ checkCommonSuffix("abcd", "axcd", 2);
+ checkNotCommonSuffix("abcd", "axcd", 3);
+
+ checkNotCommonSuffix("abcx", "abcy", 1);
+ }
+
+ private static void checkNotCommonSuffix(String s, String p, int len) {
+ assertFalse(checkCommonSuffixSymmetric(s, p, len));
+ }
+
+ private static void checkCommonSuffix(String s, String p, int len) {
+ assertTrue(checkCommonSuffixSymmetric(s, p, len));
+ }
+
+ private static boolean checkCommonSuffixSymmetric(String s, String p, int len) {
+ boolean sp = commonSuffixOfLength(s, p, len);
+ boolean ps = commonSuffixOfLength(p, s, len);
+ assertEquals(sp, ps);
+ return sp;
+ }
+
+ @Test (expected = NullPointerException.class)
+ public void escapeCsvNull() {
+ StringUtil.escapeCsv(null);
+ }
+
+ @Test
+ public void escapeCsvEmpty() {
+ CharSequence value = "";
+ CharSequence expected = value;
+ escapeCsv(value, expected);
+ }
+
+ @Test
+ public void escapeCsvUnquoted() {
+ CharSequence value = "something";
+ CharSequence expected = value;
+ escapeCsv(value, expected);
+ }
+
+ @Test
+ public void escapeCsvAlreadyQuoted() {
+ CharSequence value = "\"something\"";
+ CharSequence expected = "\"something\"";
+ escapeCsv(value, expected);
+ }
+
+ @Test
+ public void escapeCsvWithQuote() {
+ CharSequence value = "s\"";
+ CharSequence expected = "\"s\"\"\"";
+ escapeCsv(value, expected);
+ }
+
+ @Test
+ public void escapeCsvWithQuoteInMiddle() {
+ CharSequence value = "some text\"and more text";
+ CharSequence expected = "\"some text\"\"and more text\"";
+ escapeCsv(value, expected);
+ }
+
+ @Test
+ public void escapeCsvWithQuoteInMiddleAlreadyQuoted() {
+ CharSequence value = "\"some text\"and more text\"";
+ CharSequence expected = "\"some text\"\"and more text\"";
+ escapeCsv(value, expected);
+ }
+
+ @Test
+ public void escapeCsvWithQuotedWords() {
+ CharSequence value = "\"foo\"\"goo\"";
+ CharSequence expected = "\"foo\"\"goo\"";
+ escapeCsv(value, expected);
+ }
+
+ @Test
+ public void escapeCsvWithAlreadyEscapedQuote() {
+ CharSequence value = "foo\"\"goo";
+ CharSequence expected = "foo\"\"goo";
+ escapeCsv(value, expected);
+ }
+
+ @Test
+ public void escapeCsvEndingWithQuote() {
+ CharSequence value = "some\"";
+ CharSequence expected = "\"some\"\"\"";
+ escapeCsv(value, expected);
+ }
+
+ @Test
+ public void escapeCsvWithSingleQuote() {
+ CharSequence value = "\"";
+ CharSequence expected = "\"\"\"\"";
+ escapeCsv(value, expected);
+ }
+
+ @Test
+ public void escapeCsvWithSingleQuoteAndCharacter() {
+ CharSequence value = "\"f";
+ CharSequence expected = "\"\"\"f\"";
+ escapeCsv(value, expected);
+ }
+
+ @Test
+ public void escapeCsvAlreadyEscapedQuote() {
+ CharSequence value = "\"some\"\"";
+ CharSequence expected = "\"some\"\"\"";
+ escapeCsv(value, expected);
+ }
+
+ @Test
+ public void escapeCsvQuoted() {
+ CharSequence value = "\"foo,goo\"";
+ CharSequence expected = value;
+ escapeCsv(value, expected);
+ }
+
+ @Test
+ public void escapeCsvWithLineFeed() {
+ CharSequence value = "some text\n more text";
+ CharSequence expected = "\"some text\n more text\"";
+ escapeCsv(value, expected);
+ }
+
+ @Test
+ public void escapeCsvWithSingleLineFeedCharacter() {
+ CharSequence value = "\n";
+ CharSequence expected = "\"\n\"";
+ escapeCsv(value, expected);
+ }
+
+ @Test
+ public void escapeCsvWithMultipleLineFeedCharacter() {
+ CharSequence value = "\n\n";
+ CharSequence expected = "\"\n\n\"";
+ escapeCsv(value, expected);
+ }
+
+ @Test
+ public void escapeCsvWithQuotedAndLineFeedCharacter() {
+ CharSequence value = " \" \n ";
+ CharSequence expected = "\" \"\" \n \"";
+ escapeCsv(value, expected);
+ }
+
+ @Test
+ public void escapeCsvWithLineFeedAtEnd() {
+ CharSequence value = "testing\n";
+ CharSequence expected = "\"testing\n\"";
+ escapeCsv(value, expected);
+ }
+
+ @Test
+ public void escapeCsvWithComma() {
+ CharSequence value = "test,ing";
+ CharSequence expected = "\"test,ing\"";
+ escapeCsv(value, expected);
+ }
+
+ @Test
+ public void escapeCsvWithSingleComma() {
+ CharSequence value = ",";
+ CharSequence expected = "\",\"";
+ escapeCsv(value, expected);
+ }
+
+ @Test
+ public void escapeCsvWithSingleCarriageReturn() {
+ CharSequence value = "\r";
+ CharSequence expected = "\"\r\"";
+ escapeCsv(value, expected);
+ }
+
+ @Test
+ public void escapeCsvWithMultipleCarriageReturn() {
+ CharSequence value = "\r\r";
+ CharSequence expected = "\"\r\r\"";
+ escapeCsv(value, expected);
+ }
+
+ @Test
+ public void escapeCsvWithCarriageReturn() {
+ CharSequence value = "some text\r more text";
+ CharSequence expected = "\"some text\r more text\"";
+ escapeCsv(value, expected);
+ }
+
+ @Test
+ public void escapeCsvWithQuotedAndCarriageReturnCharacter() {
+ CharSequence value = "\"\r";
+ CharSequence expected = "\"\"\"\r\"";
+ escapeCsv(value, expected);
+ }
+
+ @Test
+ public void escapeCsvWithCarriageReturnAtEnd() {
+ CharSequence value = "testing\r";
+ CharSequence expected = "\"testing\r\"";
+ escapeCsv(value, expected);
+ }
+
+ @Test
+ public void escapeCsvWithCRLFCharacter() {
+ CharSequence value = "\r\n";
+ CharSequence expected = "\"\r\n\"";
+ escapeCsv(value, expected);
+ }
+
+ private static void escapeCsv(CharSequence value, CharSequence expected) {
+ CharSequence escapedValue = value;
+ for (int i = 0; i < 10; ++i) {
+ escapedValue = StringUtil.escapeCsv(escapedValue);
+ assertEquals(expected, escapedValue.toString());
+ }
+ }
+
+ @Test
public void testSimpleClassName() throws Exception {
testSimpleClassName(String.class);
}
diff -Nru netty-4.0.33/debian/changelog netty-4.0.34/debian/changelog
--- netty-4.0.33/debian/changelog 2015-11-19 22:38:03.000000000 +0000
+++ netty-4.0.34/debian/changelog 2016-01-31 22:39:21.000000000 +0000
@@ -1,3 +1,13 @@
+netty (1:4.0.34-1) unstable; urgency=medium
+
+ * Team upload.
+ * New upstream release
+ - Depend on netty-tcnative (>= 1.1.33.Fork11)
+ * Build with the DH sequencer instead of CDBS
+ * Made the versions.properties embedded in the jar files reproducible
+
+ -- Emmanuel Bourg Sun, 31 Jan 2016 23:39:15 +0100
+
netty (1:4.0.33-1) unstable; urgency=medium
* Team upload.
diff -Nru netty-4.0.33/debian/control netty-4.0.34/debian/control
--- netty-4.0.33/debian/control 2015-11-19 22:27:45.000000000 +0000
+++ netty-4.0.34/debian/control 2016-01-31 22:38:33.000000000 +0000
@@ -8,7 +8,6 @@
Damien Raude-Morvan
Build-Depends: ant,
ant-contrib (>= 1.0~b3+svn177-7~),
- cdbs,
debhelper (>= 9),
default-jdk,
ivy,
@@ -23,7 +22,7 @@
libmaven-dependency-plugin-java,
libmaven-scm-java,
libmockito-java,
- libnetty-tcnative-java,
+ libnetty-tcnative-java (>= 1.1.33.Fork11),
libprotobuf-java,
libxz-java,
maven-debian-helper (>= 1.5)
diff -Nru netty-4.0.33/debian/patches/05-reproducible-versions-properties.patch netty-4.0.34/debian/patches/05-reproducible-versions-properties.patch
--- netty-4.0.33/debian/patches/05-reproducible-versions-properties.patch 1970-01-01 00:00:00.000000000 +0000
+++ netty-4.0.34/debian/patches/05-reproducible-versions-properties.patch 2016-01-31 22:31:09.000000000 +0000
@@ -0,0 +1,22 @@
+Description: Make the versions.properties files reproducible
+Author: Emmanuel Bourg
+Forwarded: not-needed
+--- a/pom.xml
++++ b/pom.xml
+@@ -874,11 +874,11 @@
+
+
+
+-
+-
+-
+-
+-
++
++
++
++
++
+
+
+
diff -Nru netty-4.0.33/debian/patches/series netty-4.0.34/debian/patches/series
--- netty-4.0.33/debian/patches/series 2015-11-19 22:27:45.000000000 +0000
+++ netty-4.0.34/debian/patches/series 2016-01-31 22:38:33.000000000 +0000
@@ -2,3 +2,4 @@
02-ignore-enforcer-rules.patch
03-ignore-jboss-marshalling.patch
04-netty-all-light.patch
+05-reproducible-versions-properties.patch
diff -Nru netty-4.0.33/debian/rules netty-4.0.34/debian/rules
--- netty-4.0.33/debian/rules 2015-11-19 22:27:45.000000000 +0000
+++ netty-4.0.34/debian/rules 2016-01-31 22:09:00.000000000 +0000
@@ -1,14 +1,12 @@
#!/usr/bin/make -f
-include /usr/share/cdbs/1/rules/debhelper.mk
-include /usr/share/cdbs/1/class/maven.mk
+export BUILD_DATE=$(shell date --date='@${SOURCE_DATE_EPOCH}' --utc +'%Y-%m-%d %H:%M:%S')
-JAVA_HOME := /usr/lib/jvm/default-java
+%:
+ dh $@ --buildsystem=maven
-common-configure-indep::
- # Create an empty manifest to workaround an issue with maven-jar-plugin
- mkdir -p all/target/classes/META-INF/
- touch all/target/classes/META-INF/MANIFEST.MF
+override_dh_auto_build:
+ dh_auto_build -- package -Dbuild.date='${BUILD_DATE}'
get-orig-source:
uscan --download-current-version --force-download --no-symlink
diff -Nru netty-4.0.33/example/pom.xml netty-4.0.34/example/pom.xml
--- netty-4.0.33/example/pom.xml 2015-11-03 13:18:17.000000000 +0000
+++ netty-4.0.34/example/pom.xml 2016-01-29 08:23:46.000000000 +0000
@@ -21,7 +21,7 @@
io.nettynetty-parent
- 4.0.33.Final
+ 4.0.34.Finalnetty-example
@@ -111,7 +111,7 @@
${java.home}/bin/java
${argLine.common}
- ${argLine.bootcp}
+ ${argLine.alpnAgent}
-classpath %classpath
${argLine.leak}
${argLine.coverage}
diff -Nru netty-4.0.33/handler/pom.xml netty-4.0.34/handler/pom.xml
--- netty-4.0.33/handler/pom.xml 2015-11-03 13:18:17.000000000 +0000
+++ netty-4.0.34/handler/pom.xml 2016-01-29 08:23:46.000000000 +0000
@@ -20,7 +20,7 @@
io.nettynetty-parent
- 4.0.33.Final
+ 4.0.34.Finalnetty-handler
@@ -61,22 +61,10 @@
true
- org.mortbay.jetty.npn
- npn-boot
- provided
- true
-
- org.eclipse.jetty.alpnalpn-apitrue
-
- org.mortbay.jetty.alpn
- alpn-boot
- provided
- true
-
diff -Nru netty-4.0.33/handler/src/main/java/io/netty/handler/ssl/ApplicationProtocolNegotiationHandler.java netty-4.0.34/handler/src/main/java/io/netty/handler/ssl/ApplicationProtocolNegotiationHandler.java
--- netty-4.0.33/handler/src/main/java/io/netty/handler/ssl/ApplicationProtocolNegotiationHandler.java 2015-11-03 13:18:17.000000000 +0000
+++ netty-4.0.34/handler/src/main/java/io/netty/handler/ssl/ApplicationProtocolNegotiationHandler.java 2016-01-29 08:23:46.000000000 +0000
@@ -99,8 +99,7 @@
String protocol = sslHandler.applicationProtocol();
configurePipeline(ctx, protocol != null? protocol : fallbackProtocol);
} else {
- logger.warn("{} TLS handshake failed:", ctx.channel(), handshakeEvent.cause());
- ctx.close();
+ handshakeFailure(ctx, handshakeEvent.cause());
}
}
@@ -117,6 +116,14 @@
*/
protected abstract void configurePipeline(ChannelHandlerContext ctx, String protocol) throws Exception;
+ /**
+ * Invoked on failed initial SSL/TLS handshake.
+ */
+ protected void handshakeFailure(ChannelHandlerContext ctx, Throwable cause) throws Exception {
+ logger.warn("{} TLS handshake failed:", ctx.channel(), cause);
+ ctx.close();
+ }
+
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
logger.warn("{} Failed to select the application-level protocol:", ctx.channel(), cause);
diff -Nru netty-4.0.33/handler/src/main/java/io/netty/handler/ssl/OpenSslClientContext.java netty-4.0.34/handler/src/main/java/io/netty/handler/ssl/OpenSslClientContext.java
--- netty-4.0.33/handler/src/main/java/io/netty/handler/ssl/OpenSslClientContext.java 2015-11-03 13:18:17.000000000 +0000
+++ netty-4.0.34/handler/src/main/java/io/netty/handler/ssl/OpenSslClientContext.java 2016-01-29 08:23:46.000000000 +0000
@@ -191,17 +191,6 @@
"Either both keyCertChainFile and keyFile needs to be null or none of them");
}
synchronized (OpenSslContext.class) {
- if (trustCertChainFile != null) {
- /* Load the certificate chain. We must NOT skip the first cert when client mode */
- if (!SSLContext.setCertificateChainFile(ctx, trustCertChainFile.getPath(), false)) {
- long error = SSL.getLastErrorNumber();
- if (OpenSsl.isError(error)) {
- throw new SSLException(
- "failed to set certificate chain: "
- + trustCertChainFile + " (" + SSL.getErrorString(error) + ')');
- }
- }
- }
if (keyCertChainFile != null && keyFile != null) {
/* Load the certificate file and private key. */
try {
@@ -214,6 +203,16 @@
" (" + SSL.getErrorString(error) + ')');
}
}
+ // We may have more then one cert in the chain so add all of them now. We must NOT skip the
+ // first cert when client mode.
+ if (!SSLContext.setCertificateChainFile(ctx, keyCertChainFile.getPath(), false)) {
+ long error = SSL.getLastErrorNumber();
+ if (OpenSsl.isError(error)) {
+ throw new SSLException(
+ "failed to set certificate chain: "
+ + keyCertChainFile + " (" + SSL.getErrorString(error) + ')');
+ }
+ }
} catch (SSLException e) {
throw e;
} catch (Exception e) {
@@ -281,28 +280,6 @@
"Either both keyCertChain and key needs to be null or none of them");
}
synchronized (OpenSslContext.class) {
- if (trustCertChain != null) {
- long trustCertChainBio = 0;
-
- try {
- trustCertChainBio = toBIO(trustCertChain);
- /* Load the certificate chain. We must NOT skip the first cert when client mode */
- if (!SSLContext.setCertificateChainBio(ctx, trustCertChainBio, false)) {
- long error = SSL.getLastErrorNumber();
- if (OpenSsl.isError(error)) {
- throw new SSLException(
- "failed to set certificate chain: " + SSL.getErrorString(error));
- }
- }
- } catch (Exception e) {
- throw new SSLException(
- "failed to set certificate chain", e);
- } finally {
- if (trustCertChainBio != 0) {
- SSL.freeBIO(trustCertChainBio);
- }
- }
- }
if (keyCertChain != null && key != null) {
/* Load the certificate file and private key. */
long keyBio = 0;
@@ -321,6 +298,15 @@
+ SSL.getErrorString(error));
}
}
+ // We may have more then one cert in the chain so add all of them now. We must NOT skip the
+ // first cert when client mode.
+ if (!SSLContext.setCertificateChainBio(ctx, keyCertChainBio, false)) {
+ long error = SSL.getLastErrorNumber();
+ if (OpenSsl.isError(error)) {
+ throw new SSLException(
+ "failed to set certificate chain: " + SSL.getErrorString(error));
+ }
+ }
} catch (SSLException e) {
throw e;
} catch (Exception e) {
diff -Nru netty-4.0.33/handler/src/main/java/io/netty/handler/ssl/OpenSslContext.java netty-4.0.34/handler/src/main/java/io/netty/handler/ssl/OpenSslContext.java
--- netty-4.0.33/handler/src/main/java/io/netty/handler/ssl/OpenSslContext.java 2015-11-03 13:18:17.000000000 +0000
+++ netty-4.0.34/handler/src/main/java/io/netty/handler/ssl/OpenSslContext.java 2016-01-29 08:23:46.000000000 +0000
@@ -295,10 +295,8 @@
@Override
public final SSLEngine newEngine(ByteBufAllocator alloc, String peerHost, int peerPort) {
- final OpenSslEngine engine = new OpenSslEngine(ctx, alloc, isClient(), sessionContext(), apn, engineMap,
+ return new OpenSslEngine(ctx, alloc, isClient(), sessionContext(), apn, engineMap,
rejectRemoteInitiatedRenegotiation, peerHost, peerPort, keyCertChain, clientAuth);
- engineMap.add(engine);
- return engine;
}
/**
@@ -488,7 +486,18 @@
ByteBuf buffer = Unpooled.directBuffer();
try {
buffer.writeBytes(BEGIN_PRIVATE_KEY);
- buffer.writeBytes(Base64.encode(Unpooled.wrappedBuffer(key.getEncoded()), true));
+ ByteBuf wrappedBuf = Unpooled.wrappedBuffer(key.getEncoded());
+ final ByteBuf encodedBuf;
+ try {
+ encodedBuf = Base64.encode(wrappedBuf, true);
+ try {
+ buffer.writeBytes(encodedBuf);
+ } finally {
+ encodedBuf.release();
+ }
+ } finally {
+ wrappedBuf.release();
+ }
buffer.writeBytes(END_PRIVATE_KEY);
return newBIO(buffer);
} finally {
@@ -508,7 +517,17 @@
try {
for (X509Certificate cert: certChain) {
buffer.writeBytes(BEGIN_CERT);
- buffer.writeBytes(Base64.encode(Unpooled.wrappedBuffer(cert.getEncoded()), true));
+ ByteBuf wrappedBuf = Unpooled.wrappedBuffer(cert.getEncoded());
+ try {
+ ByteBuf encodedBuf = Base64.encode(wrappedBuf, true);
+ try {
+ buffer.writeBytes(encodedBuf);
+ } finally {
+ encodedBuf.release();
+ }
+ } finally {
+ wrappedBuf.release();
+ }
buffer.writeBytes(END_CERT);
}
return newBIO(buffer);
diff -Nru netty-4.0.33/handler/src/main/java/io/netty/handler/ssl/OpenSslEngine.java netty-4.0.34/handler/src/main/java/io/netty/handler/ssl/OpenSslEngine.java
--- netty-4.0.33/handler/src/main/java/io/netty/handler/ssl/OpenSslEngine.java 2015-11-03 13:18:17.000000000 +0000
+++ netty-4.0.34/handler/src/main/java/io/netty/handler/ssl/OpenSslEngine.java 2016-01-29 08:23:46.000000000 +0000
@@ -148,7 +148,6 @@
private HandshakeState handshakeState = HandshakeState.NOT_STARTED;
private boolean receivedShutdown;
- @SuppressWarnings("UnusedDeclaration")
private volatile int destroyed;
private volatile ClientAuth clientAuth = ClientAuth.NONE;
@@ -168,7 +167,7 @@
private final OpenSslApplicationProtocolNegotiator apn;
private final boolean rejectRemoteInitiatedRenegation;
private final OpenSslSession session;
- private final java.security.cert.Certificate[] localCerts;
+ private final Certificate[] localCerts;
private final ByteBuffer[] singleSrcBuffer = new ByteBuffer[1];
private final ByteBuffer[] singleDstBuffer = new ByteBuffer[1];
@@ -202,7 +201,7 @@
boolean clientMode, OpenSslSessionContext sessionContext,
OpenSslApplicationProtocolNegotiator apn, OpenSslEngineMap engineMap,
boolean rejectRemoteInitiatedRenegation, String peerHost, int peerPort,
- java.security.cert.Certificate[] localCerts,
+ Certificate[] localCerts,
ClientAuth clientAuth) {
super(peerHost, peerPort);
OpenSsl.ensureAvailability();
@@ -212,7 +211,6 @@
this.alloc = checkNotNull(alloc, "alloc");
this.apn = checkNotNull(apn, "apn");
- this.clientAuth = clientMode ? ClientAuth.NONE : checkNotNull(clientAuth, "clientAuth");
ssl = SSL.newSSL(sslCtx, !clientMode);
session = new OpenSslSession(sessionContext);
networkBIO = SSL.makeNetworkBIO(ssl);
@@ -220,16 +218,25 @@
this.engineMap = engineMap;
this.rejectRemoteInitiatedRenegation = rejectRemoteInitiatedRenegation;
this.localCerts = localCerts;
+
+ // Set the client auth mode, this needs to be done via setClientAuth(...) method so we actually call the
+ // needed JNI methods.
+ setClientAuth(clientMode ? ClientAuth.NONE : checkNotNull(clientAuth, "clientAuth"));
}
@Override
- public SSLSession getHandshakeSession() {
- if (handshakeState != HandshakeState.NOT_STARTED) {
- // handshake started we are able to return the session.
+ public synchronized SSLSession getHandshakeSession() {
+ // Javadocs state return value should be:
+ // null if this instance is not currently handshaking, or if the current handshake has not
+ // progressed far enough to create a basic SSLSession. Otherwise, this method returns the
+ // SSLSession currently being negotiated.
+ switch(handshakeState) {
+ case NOT_STARTED:
+ case FINISHED:
+ return null;
+ default:
return session;
}
- // As stated by the javadocs of getHandshakeSession() we should return null if the handshake not started yet.
- return null;
}
/**
@@ -518,7 +525,7 @@
break;
default:
// Everything else is considered as error
- shutdownWithError("SSL_write");
+ throw shutdownWithError("SSL_write");
}
}
@@ -540,24 +547,15 @@
return newResult(bytesConsumed, bytesProduced, status);
}
- private void checkPendingHandshakeException() throws SSLHandshakeException {
- if (handshakeException != null) {
- SSLHandshakeException exception = handshakeException;
- handshakeException = null;
- shutdown();
- throw exception;
- }
- }
-
/**
* Log the error, shutdown the engine and throw an exception.
*/
- private void shutdownWithError(String operations) throws SSLException {
+ private SSLException shutdownWithError(String operations) {
String err = SSL.getLastError();
- shutdownWithError(operations, err);
+ return shutdownWithError(operations, err);
}
- private void shutdownWithError(String operation, String err) throws SSLException {
+ private SSLException shutdownWithError(String operation, String err) {
if (logger.isDebugEnabled()) {
logger.debug("{} failed: OpenSSL error: {}", operation, err);
}
@@ -565,9 +563,9 @@
// There was an internal error -- shutdown
shutdown();
if (handshakeState == HandshakeState.FINISHED) {
- throw new SSLException(err);
+ return new SSLException(err);
}
- throw new SSLHandshakeException(err);
+ return new SSLHandshakeException(err);
}
public synchronized SSLEngineResult unwrap(
@@ -725,8 +723,7 @@
// break to the outer loop
return newResult(bytesConsumed, bytesProduced, status);
default:
- // Everything else is considered as error so shutdown and throw an exceptions
- shutdownWithError("SSL_read");
+ return sslReadErrorResult(SSL.getLastErrorNumber(), bytesConsumed, bytesProduced);
}
}
}
@@ -737,7 +734,7 @@
// We do not check SSL_get_error as we are not interested in any error that is not fatal.
int err = SSL.getLastErrorNumber();
if (OpenSsl.isError(err)) {
- shutdownWithError("SSL_read", SSL.getErrorString(err));
+ return sslReadErrorResult(err, bytesConsumed, bytesProduced);
}
}
}
@@ -756,6 +753,24 @@
return newResult(bytesConsumed, bytesProduced, status);
}
+ private SSLEngineResult sslReadErrorResult(int err, int bytesConsumed, int bytesProduced) throws SSLException {
+ String errStr = SSL.getErrorString(err);
+
+ // Check if we have a pending handshakeException and if so see if we need to consume all pending data from the
+ // BIO first or can just shutdown and throw it now.
+ // This is needed so we ensure close_notify etc is correctly send to the remote peer.
+ // See https://github.com/netty/netty/issues/3900
+ if (SSL.pendingWrittenBytesInBIO(networkBIO) > 0) {
+ if (handshakeException == null && handshakeState != HandshakeState.FINISHED) {
+ // we seems to have data left that needs to be transfered and so the user needs
+ // call wrap(...). Store the error so we can pick it up later.
+ handshakeException = new SSLHandshakeException(errStr);
+ }
+ return new SSLEngineResult(OK, NEED_WRAP, bytesConsumed, bytesProduced);
+ }
+ throw shutdownWithError("SSL_read", errStr);
+ }
+
private int pendingAppData() {
// There won't be any application data until we're done handshaking.
// We first check handshakeFinished to eliminate the overhead of extra JNI call if possible.
@@ -1065,21 +1080,29 @@
// Enable all and then disable what we not want
SSL.setOptions(ssl, SSL.SSL_OP_ALL);
+ // Clear out options which disable protocols
+ SSL.clearOptions(ssl, SSL.SSL_OP_NO_SSLv2 | SSL.SSL_OP_NO_SSLv3 | SSL.SSL_OP_NO_TLSv1 |
+ SSL.SSL_OP_NO_TLSv1_1 | SSL.SSL_OP_NO_TLSv1_2);
+
+ int opts = 0;
if (!sslv2) {
- SSL.setOptions(ssl, SSL.SSL_OP_NO_SSLv2);
+ opts |= SSL.SSL_OP_NO_SSLv2;
}
if (!sslv3) {
- SSL.setOptions(ssl, SSL.SSL_OP_NO_SSLv3);
+ opts |= SSL.SSL_OP_NO_SSLv3;
}
if (!tlsv1) {
- SSL.setOptions(ssl, SSL.SSL_OP_NO_TLSv1);
+ opts |= SSL.SSL_OP_NO_TLSv1;
}
if (!tlsv1_1) {
- SSL.setOptions(ssl, SSL.SSL_OP_NO_TLSv1_1);
+ opts |= SSL.SSL_OP_NO_TLSv1_1;
}
if (!tlsv1_2) {
- SSL.setOptions(ssl, SSL.SSL_OP_NO_TLSv1_2);
+ opts |= SSL.SSL_OP_NO_TLSv1_2;
}
+
+ // Disable protocols we do not want
+ SSL.setOptions(ssl, opts);
} else {
throw new IllegalStateException("failed to enable protocols: " + Arrays.asList(protocols));
}
@@ -1128,7 +1151,7 @@
// https://github.com/apache/httpd/blob/2.4.16/modules/ssl/ssl_engine_kernel.c#L812
// http://h71000.www7.hp.com/doc/83final/ba554_90007/ch04s03.html
if (SSL.renegotiate(ssl) != 1 || SSL.doHandshake(ssl) != 1) {
- shutdownWithError("renegotiation failed");
+ throw shutdownWithError("renegotiation failed");
}
SSL.setState(ssl, SSL.SSL_ST_ACCEPT);
@@ -1158,9 +1181,37 @@
return FINISHED;
}
checkEngineClosed();
+
+ // Check if we have a pending handshakeException and if so see if we need to consume all pending data from the
+ // BIO first or can just shutdown and throw it now.
+ // This is needed so we ensure close_notify etc is correctly send to the remote peer.
+ // See https://github.com/netty/netty/issues/3900
+ SSLHandshakeException exception = handshakeException;
+ if (exception != null) {
+ if (SSL.pendingWrittenBytesInBIO(networkBIO) > 0) {
+ // There is something pending, we need to consume it first via a WRAP so we not loose anything.
+ return NEED_WRAP;
+ }
+ // No more data left to send to the remote peer, so null out the exception field, shutdown and throw
+ // the exception.
+ handshakeException = null;
+ shutdown();
+ throw exception;
+ }
+
+ // Adding the OpenSslEngine to the OpenSslEngineMap so it can be used in the AbstractCertificateVerifier.
+ engineMap.add(this);
+
int code = SSL.doHandshake(ssl);
if (code <= 0) {
- checkPendingHandshakeException();
+ // Check if we have a pending exception that was created during the handshake and if so throw it after
+ // shutdown the connection.
+ if (handshakeException != null) {
+ exception = handshakeException;
+ handshakeException = null;
+ shutdown();
+ throw exception;
+ }
int sslError = SSL.getError(ssl, code);
@@ -1170,13 +1221,11 @@
return pendingStatus(SSL.pendingWrittenBytesInBIO(networkBIO));
default:
// Everything else is considered as error
- shutdownWithError("SSL_do_handshake");
+ throw shutdownWithError("SSL_do_handshake");
}
}
-
// if SSL_do_handshake returns > 0 or sslError == SSL.SSL_ERROR_NAME it means the handshake was finished.
session.handshakeFinished();
-
return FINISHED;
}
@@ -1205,18 +1254,12 @@
@Override
public synchronized SSLEngineResult.HandshakeStatus getHandshakeStatus() {
// Check if we are in the initial handshake phase or shutdown phase
- if (needPendingStatus()) {
- return pendingStatus(SSL.pendingWrittenBytesInBIO(networkBIO));
- }
- return NOT_HANDSHAKING;
+ return needPendingStatus() ? pendingStatus(SSL.pendingWrittenBytesInBIO(networkBIO)) : NOT_HANDSHAKING;
}
private SSLEngineResult.HandshakeStatus getHandshakeStatus(int pending) {
// Check if we are in the initial handshake phase or shutdown phase
- if (needPendingStatus()) {
- return pendingStatus(pending);
- }
- return NOT_HANDSHAKING;
+ return needPendingStatus() ? pendingStatus(pending) : NOT_HANDSHAKING;
}
private boolean needPendingStatus() {
diff -Nru netty-4.0.33/handler/src/main/java/io/netty/handler/ssl/OpenSslServerContext.java netty-4.0.34/handler/src/main/java/io/netty/handler/ssl/OpenSslServerContext.java
--- netty-4.0.33/handler/src/main/java/io/netty/handler/ssl/OpenSslServerContext.java 2015-11-03 13:18:17.000000000 +0000
+++ netty-4.0.34/handler/src/main/java/io/netty/handler/ssl/OpenSslServerContext.java 2016-01-29 08:23:46.000000000 +0000
@@ -321,6 +321,7 @@
ClientAuth.NONE);
OpenSsl.ensureAvailability();
+ checkKeyManagerFactory(keyManagerFactory);
checkNotNull(keyCertChainFile, "keyCertChainFile");
if (!keyCertChainFile.isFile()) {
throw new IllegalArgumentException("keyCertChainFile is not a file: " + keyCertChainFile);
@@ -420,6 +421,7 @@
clientAuth);
OpenSsl.ensureAvailability();
+ checkKeyManagerFactory(keyManagerFactory);
checkNotNull(keyCertChain, "keyCertChainFile");
checkNotNull(key, "keyFile");
@@ -528,4 +530,11 @@
public OpenSslServerSessionContext sessionContext() {
return sessionContext;
}
+
+ private static void checkKeyManagerFactory(KeyManagerFactory keyManagerFactory) {
+ if (keyManagerFactory != null) {
+ throw new IllegalArgumentException(
+ "KeyManagerFactory is currently not supported with OpenSslServerContext");
+ }
+ }
}
diff -Nru netty-4.0.33/handler/src/main/java/io/netty/handler/ssl/SniHandler.java netty-4.0.34/handler/src/main/java/io/netty/handler/ssl/SniHandler.java
--- netty-4.0.33/handler/src/main/java/io/netty/handler/ssl/SniHandler.java 2015-11-03 13:18:17.000000000 +0000
+++ netty-4.0.34/handler/src/main/java/io/netty/handler/ssl/SniHandler.java 2016-01-29 08:23:46.000000000 +0000
@@ -37,14 +37,19 @@
*/
public class SniHandler extends ByteToMessageDecoder {
+ // Maximal number of ssl records to inspect before fallback to the default SslContext.
+ private static final int MAX_SSL_RECORDS = 4;
+
private static final InternalLogger logger =
InternalLoggerFactory.getInstance(SniHandler.class);
+ private static final Selection EMPTY_SELECTION = new Selection(null, null);
+
private final DomainNameMapping mapping;
- private boolean handshaken;
- private volatile String hostname;
- private volatile SslContext selectedContext;
+ private boolean handshakeFailed;
+
+ private volatile Selection selection = EMPTY_SELECTION;
/**
* Create a SNI detection handler with configured {@link SslContext}
@@ -59,127 +64,200 @@
}
this.mapping = (DomainNameMapping) mapping;
- handshaken = false;
}
/**
* @return the selected hostname
*/
public String hostname() {
- return hostname;
+ return selection.hostname;
}
/**
* @return the selected sslcontext
*/
public SslContext sslContext() {
- return selectedContext;
+ return selection.context;
}
@Override
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List out) throws Exception {
- if (!handshaken && in.readableBytes() >= 5) {
- String hostname = sniHostNameFromHandshakeInfo(in);
- if (hostname != null) {
- hostname = IDN.toASCII(hostname, IDN.ALLOW_UNASSIGNED).toLowerCase(Locale.US);
- }
- this.hostname = hostname;
-
- // the mapping will return default context when this.hostname is null
- selectedContext = mapping.map(hostname);
- }
-
- if (handshaken) {
- SslHandler sslHandler = selectedContext.newHandler(ctx.alloc());
- ctx.pipeline().replace(this, SslHandler.class.getName(), sslHandler);
- }
- }
-
- private String sniHostNameFromHandshakeInfo(ByteBuf in) {
- int readerIndex = in.readerIndex();
- try {
- int command = in.getUnsignedByte(readerIndex);
-
- // tls, but not handshake command
- switch (command) {
- case SslConstants.SSL_CONTENT_TYPE_CHANGE_CIPHER_SPEC:
- case SslConstants.SSL_CONTENT_TYPE_ALERT:
- case SslConstants.SSL_CONTENT_TYPE_APPLICATION_DATA:
- return null;
- case SslConstants.SSL_CONTENT_TYPE_HANDSHAKE:
- break;
- default:
- //not tls or sslv3, do not try sni
- handshaken = true;
- return null;
- }
-
- int majorVersion = in.getUnsignedByte(readerIndex + 1);
+ if (!handshakeFailed) {
+ final int writerIndex = in.writerIndex();
+ try {
+ loop:
+ for (int i = 0; i < MAX_SSL_RECORDS; i++) {
+ final int readerIndex = in.readerIndex();
+ final int readableBytes = writerIndex - readerIndex;
+ if (readableBytes < SslUtils.SSL_RECORD_HEADER_LENGTH) {
+ // Not enough data to determine the record type and length.
+ return;
+ }
- // SSLv3 or TLS
- if (majorVersion == 3) {
+ final int command = in.getUnsignedByte(readerIndex);
- int packetLength = in.getUnsignedShort(readerIndex + 3) + 5;
+ // tls, but not handshake command
+ switch (command) {
+ case SslUtils.SSL_CONTENT_TYPE_CHANGE_CIPHER_SPEC:
+ case SslUtils.SSL_CONTENT_TYPE_ALERT:
+ final int len = SslUtils.getEncryptedPacketLength(in, readerIndex);
+
+ // Not an SSL/TLS packet
+ if (len == -1) {
+ handshakeFailed = true;
+ NotSslRecordException e = new NotSslRecordException(
+ "not an SSL/TLS record: " + ByteBufUtil.hexDump(in));
+ in.skipBytes(in.readableBytes());
+ ctx.fireExceptionCaught(e);
- if (in.readableBytes() >= packetLength) {
- // decode the ssl client hello packet
- // we have to skip some var-length fields
- int offset = readerIndex + 43;
-
- int sessionIdLength = in.getUnsignedByte(offset);
- offset += sessionIdLength + 1;
-
- int cipherSuitesLength = in.getUnsignedShort(offset);
- offset += cipherSuitesLength + 2;
-
- int compressionMethodLength = in.getUnsignedByte(offset);
- offset += compressionMethodLength + 1;
-
- int extensionsLength = in.getUnsignedShort(offset);
- offset += 2;
- int extensionsLimit = offset + extensionsLength;
-
- while (offset < extensionsLimit) {
- int extensionType = in.getUnsignedShort(offset);
- offset += 2;
-
- int extensionLength = in.getUnsignedShort(offset);
- offset += 2;
-
- // SNI
- if (extensionType == 0) {
- handshaken = true;
- int serverNameType = in.getUnsignedByte(offset + 2);
- if (serverNameType == 0) {
- int serverNameLength = in.getUnsignedShort(offset + 3);
- return in.toString(offset + 5, serverNameLength,
- CharsetUtil.UTF_8);
- } else {
- // invalid enum value
- return null;
+ SslUtils.notifyHandshakeFailure(ctx, e);
+ return;
+ }
+ if (writerIndex - readerIndex - SslUtils.SSL_RECORD_HEADER_LENGTH < len) {
+ // Not enough data
+ return;
}
- }
+ // increase readerIndex and try again.
+ in.skipBytes(len);
+ continue;
+ case SslUtils.SSL_CONTENT_TYPE_HANDSHAKE:
+ final int majorVersion = in.getUnsignedByte(readerIndex + 1);
+
+ // SSLv3 or TLS
+ if (majorVersion == 3) {
+ final int packetLength = in.getUnsignedShort(readerIndex + 3) +
+ SslUtils.SSL_RECORD_HEADER_LENGTH;
+
+ if (readableBytes < packetLength) {
+ // client hello incomplete; try again to decode once more data is ready.
+ return;
+ }
+
+ // See https://tools.ietf.org/html/rfc5246#section-7.4.1.2
+ //
+ // Decode the ssl client hello packet.
+ // We have to skip bytes until SessionID (which sum to 43 bytes).
+ //
+ // struct {
+ // ProtocolVersion client_version;
+ // Random random;
+ // SessionID session_id;
+ // CipherSuite cipher_suites<2..2^16-2>;
+ // CompressionMethod compression_methods<1..2^8-1>;
+ // select (extensions_present) {
+ // case false:
+ // struct {};
+ // case true:
+ // Extension extensions<0..2^16-1>;
+ // };
+ // } ClientHello;
+ //
+
+ final int endOffset = readerIndex + packetLength;
+ int offset = readerIndex + 43;
+
+ if (endOffset - offset < 6) {
+ break loop;
+ }
+
+ final int sessionIdLength = in.getUnsignedByte(offset);
+ offset += sessionIdLength + 1;
+
+ final int cipherSuitesLength = in.getUnsignedShort(offset);
+ offset += cipherSuitesLength + 2;
+
+ final int compressionMethodLength = in.getUnsignedByte(offset);
+ offset += compressionMethodLength + 1;
+
+ final int extensionsLength = in.getUnsignedShort(offset);
+ offset += 2;
+ final int extensionsLimit = offset + extensionsLength;
+
+ if (extensionsLimit > endOffset) {
+ // Extensions should never exceed the record boundary.
+ break loop;
+ }
+
+ for (;;) {
+ if (extensionsLimit - offset < 4) {
+ break loop;
+ }
+
+ final int extensionType = in.getUnsignedShort(offset);
+ offset += 2;
+
+ final int extensionLength = in.getUnsignedShort(offset);
+ offset += 2;
+
+ if (extensionsLimit - offset < extensionLength) {
+ break loop;
+ }
+
+ // SNI
+ // See https://tools.ietf.org/html/rfc6066#page-6
+ if (extensionType == 0) {
+ offset += 2;
+ if (extensionsLimit - offset < 3) {
+ break loop;
+ }
+
+ final int serverNameType = in.getUnsignedByte(offset);
+ offset++;
+
+ if (serverNameType == 0) {
+ final int serverNameLength = in.getUnsignedShort(offset);
+ offset += 2;
+
+ if (extensionsLimit - offset < serverNameLength) {
+ break loop;
+ }
+
+ final String hostname = in.toString(offset, serverNameLength,
+ CharsetUtil.UTF_8);
+
+ select(ctx, IDN.toASCII(hostname,
+ IDN.ALLOW_UNASSIGNED).toLowerCase(Locale.US));
+ return;
+ } else {
+ // invalid enum value
+ break loop;
+ }
+ }
- offset += extensionLength;
+ offset += extensionLength;
+ }
+ }
+ // Fall-through
+ default:
+ //not tls, ssl or application data, do not try sni
+ break loop;
}
-
- handshaken = true;
- return null;
- } else {
- // client hello incomplete
- return null;
}
- } else {
- handshaken = true;
- return null;
- }
- } catch (Throwable e) {
- // unexpected encoding, ignore sni and use default
- if (logger.isDebugEnabled()) {
- logger.debug("Unexpected client hello packet: " + ByteBufUtil.hexDump(in), e);
+ } catch (Throwable e) {
+ // unexpected encoding, ignore sni and use default
+ if (logger.isDebugEnabled()) {
+ logger.debug("Unexpected client hello packet: " + ByteBufUtil.hexDump(in), e);
+ }
}
- handshaken = true;
- return null;
+ // Just select the default SslContext
+ select(ctx, null);
+ }
+ }
+
+ private void select(ChannelHandlerContext ctx, String hostname) {
+ SslContext selectedContext = mapping.map(hostname);
+ selection = new Selection(selectedContext, hostname);
+ SslHandler sslHandler = selectedContext.newHandler(ctx.alloc());
+ ctx.pipeline().replace(this, SslHandler.class.getName(), sslHandler);
+ }
+
+ private static final class Selection {
+ final SslContext context;
+ final String hostname;
+
+ Selection(SslContext context, String hostname) {
+ this.context = context;
+ this.hostname = hostname;
}
}
}
diff -Nru netty-4.0.33/handler/src/main/java/io/netty/handler/ssl/SslConstants.java netty-4.0.34/handler/src/main/java/io/netty/handler/ssl/SslConstants.java
--- netty-4.0.33/handler/src/main/java/io/netty/handler/ssl/SslConstants.java 2015-11-03 13:18:17.000000000 +0000
+++ netty-4.0.34/handler/src/main/java/io/netty/handler/ssl/SslConstants.java 1970-01-01 00:00:00.000000000 +0000
@@ -1,45 +0,0 @@
-/*
- * Copyright 2014 The Netty Project
- *
- * The Netty Project licenses this file to you under the Apache License,
- * version 2.0 (the "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations
- * under the License.
- */
-package io.netty.handler.ssl;
-
-/**
- * Constants for SSL packets.
- */
-final class SslConstants {
-
- /**
- * change cipher spec
- */
- public static final int SSL_CONTENT_TYPE_CHANGE_CIPHER_SPEC = 20;
-
- /**
- * alert
- */
- public static final int SSL_CONTENT_TYPE_ALERT = 21;
-
- /**
- * handshake
- */
- public static final int SSL_CONTENT_TYPE_HANDSHAKE = 22;
-
- /**
- * application data
- */
- public static final int SSL_CONTENT_TYPE_APPLICATION_DATA = 23;
-
- private SslConstants() {
- }
-}
diff -Nru netty-4.0.33/handler/src/main/java/io/netty/handler/ssl/SslContext.java netty-4.0.34/handler/src/main/java/io/netty/handler/ssl/SslContext.java
--- netty-4.0.33/handler/src/main/java/io/netty/handler/ssl/SslContext.java 2015-11-03 13:18:17.000000000 +0000
+++ netty-4.0.34/handler/src/main/java/io/netty/handler/ssl/SslContext.java 2016-01-29 08:23:46.000000000 +0000
@@ -902,17 +902,6 @@
return ks;
}
- static KeyStore buildKeyStore(File certChainFile, File keyFile, String keyPassword)
- throws KeyStoreException, NoSuchAlgorithmException,
- CertificateException, NoSuchPaddingException, InvalidKeySpecException,
- InvalidAlgorithmParameterException, KeyException, IOException {
- KeyStore ks = KeyStore.getInstance("JKS");
- ks.load(null, null);
- ks.setKeyEntry("key", toPrivateKey(keyFile, keyPassword),
- keyPassword == null ? null : keyPassword.toCharArray(), toX509Certificates(certChainFile));
- return ks;
- }
-
static PrivateKey toPrivateKey(File keyFile, String keyPassword) throws NoSuchAlgorithmException,
NoSuchPaddingException, InvalidKeySpecException,
InvalidAlgorithmParameterException,
diff -Nru netty-4.0.33/handler/src/main/java/io/netty/handler/ssl/SslHandler.java netty-4.0.34/handler/src/main/java/io/netty/handler/ssl/SslHandler.java
--- netty-4.0.33/handler/src/main/java/io/netty/handler/ssl/SslHandler.java 2015-11-03 13:18:17.000000000 +0000
+++ netty-4.0.34/handler/src/main/java/io/netty/handler/ssl/SslHandler.java 2016-01-29 08:23:46.000000000 +0000
@@ -66,6 +66,8 @@
import java.util.concurrent.TimeUnit;
import java.util.regex.Pattern;
+import static io.netty.handler.ssl.SslUtils.getEncryptedPacketLength;
+
/**
* Adds SSL
* · TLS and StartTLS support to a {@link Channel}. Please refer
@@ -393,10 +395,10 @@
*/
public ChannelFuture close(final ChannelPromise future) {
final ChannelHandlerContext ctx = this.ctx;
- ctx.executor().execute(new Runnable() {
+ ctx.executor().execute(new OneTimeTask() {
@Override
public void run() {
- SslHandler.this.outboundClosed = true;
+ outboundClosed = true;
engine.closeOutbound();
try {
write(ctx, Unpooled.EMPTY_BUFFER, future);
@@ -429,6 +431,10 @@
// Check if queue is not empty first because create a new ChannelException is expensive
pendingUnencryptedWrites.removeAndFailAll(new ChannelException("Pending write on removal of SslHandler"));
}
+ if (engine instanceof OpenSslEngine) {
+ // Call shutdown so we ensure all the native memory is released asap
+ ((OpenSslEngine) engine).shutdown();
+ }
}
@Override
@@ -497,8 +503,13 @@
if (!handshakePromise.isDone()) {
flushedBeforeHandshake = true;
}
- wrap(ctx, false);
- ctx.flush();
+ try {
+ wrap(ctx, false);
+ } finally {
+ // We may have written some parts of data before an exception was thrown so ensure we always flush.
+ // See https://github.com/netty/netty/issues/3900#issuecomment-172481830
+ ctx.flush();
+ }
}
private void wrap(ChannelHandlerContext ctx, boolean inUnwrap) throws SSLException {
@@ -636,6 +647,10 @@
}
} catch (SSLException e) {
setHandshakeFailure(ctx, e);
+
+ // We may have written some parts of data before an exception was thrown so ensure we always flush.
+ // See https://github.com/netty/netty/issues/3900#issuecomment-172481830
+ flushIfNeeded(ctx);
throw e;
} finally {
if (out != null) {
@@ -809,84 +824,13 @@
* Is thrown if the given {@link ByteBuf} has not at least 5 bytes to read.
*/
public static boolean isEncrypted(ByteBuf buffer) {
- if (buffer.readableBytes() < 5) {
- throw new IllegalArgumentException("buffer must have at least 5 readable bytes");
+ if (buffer.readableBytes() < SslUtils.SSL_RECORD_HEADER_LENGTH) {
+ throw new IllegalArgumentException(
+ "buffer must have at least " + SslUtils.SSL_RECORD_HEADER_LENGTH + " readable bytes");
}
return getEncryptedPacketLength(buffer, buffer.readerIndex()) != -1;
}
- /**
- * Return how much bytes can be read out of the encrypted data. Be aware that this method will not increase
- * the readerIndex of the given {@link ByteBuf}.
- *
- * @param buffer
- * The {@link ByteBuf} to read from. Be aware that it must have at least 5 bytes to read,
- * otherwise it will throw an {@link IllegalArgumentException}.
- * @return length
- * The length of the encrypted packet that is included in the buffer. This will
- * return {@code -1} if the given {@link ByteBuf} is not encrypted at all.
- * @throws IllegalArgumentException
- * Is thrown if the given {@link ByteBuf} has not at least 5 bytes to read.
- */
- private static int getEncryptedPacketLength(ByteBuf buffer, int offset) {
- int packetLength = 0;
-
- // SSLv3 or TLS - Check ContentType
- boolean tls;
- switch (buffer.getUnsignedByte(offset)) {
- case 20: // change_cipher_spec
- case 21: // alert
- case 22: // handshake
- case 23: // application_data
- tls = true;
- break;
- default:
- // SSLv2 or bad data
- tls = false;
- }
-
- if (tls) {
- // SSLv3 or TLS - Check ProtocolVersion
- int majorVersion = buffer.getUnsignedByte(offset + 1);
- if (majorVersion == 3) {
- // SSLv3 or TLS
- packetLength = buffer.getUnsignedShort(offset + 3) + 5;
- if (packetLength <= 5) {
- // Neither SSLv3 or TLSv1 (i.e. SSLv2 or bad data)
- tls = false;
- }
- } else {
- // Neither SSLv3 or TLSv1 (i.e. SSLv2 or bad data)
- tls = false;
- }
- }
-
- if (!tls) {
- // SSLv2 or bad data - Check the version
- boolean sslv2 = true;
- int headerLength = (buffer.getUnsignedByte(offset) & 0x80) != 0 ? 2 : 3;
- int majorVersion = buffer.getUnsignedByte(offset + headerLength + 1);
- if (majorVersion == 2 || majorVersion == 3) {
- // SSLv2
- if (headerLength == 2) {
- packetLength = (buffer.getShort(offset) & 0x7FFF) + 2;
- } else {
- packetLength = (buffer.getShort(offset) & 0x3FFF) + 3;
- }
- if (packetLength <= headerLength) {
- sslv2 = false;
- }
- } else {
- sslv2 = false;
- }
-
- if (!sslv2) {
- return -1;
- }
- }
- return packetLength;
- }
-
@Override
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List out) throws SSLException {
final int startOffset = in.readerIndex();
@@ -909,7 +853,7 @@
while (totalLength < OpenSslEngine.MAX_ENCRYPTED_PACKET_LENGTH) {
final int readableBytes = endOffset - offset;
- if (readableBytes < 5) {
+ if (readableBytes < SslUtils.SSL_RECORD_HEADER_LENGTH) {
break;
}
@@ -990,10 +934,7 @@
// Discard bytes of the cumulation buffer if needed.
discardSomeReadBytes();
- if (needsFlush) {
- needsFlush = false;
- ctx.flush();
- }
+ flushIfNeeded(ctx);
// If handshake is not finished yet, we need more data.
if (!ctx.channel().config().isAutoRead() && (!firedChannelRead || !handshakePromise.isDone())) {
@@ -1006,6 +947,13 @@
ctx.fireChannelReadComplete();
}
+ private void flushIfNeeded(ChannelHandlerContext ctx) {
+ if (needsFlush) {
+ needsFlush = false;
+ ctx.flush();
+ }
+ }
+
/**
* Calls {@link SSLEngine#unwrap(ByteBuffer, ByteBuffer)} with an empty buffer to handle handshakes, etc.
*/
@@ -1069,7 +1017,19 @@
case FINISHED:
setHandshakeSuccess();
wrapLater = true;
- continue;
+
+ // We 'break' here and NOT 'continue' as android API version 21 has a bug where they consume
+ // data from the buffer but NOT correctly set the SSLEngineResult.bytesConsumed().
+ // Because of this it will raise an exception on the next iteration of the for loop on android
+ // API version 21. Just doing a break will work here as produced and consumed will both be 0
+ // and so we break out of the complete for (;;) loop and so call decode(...) again later on.
+ // On other platforms this will have no negative effect as we will just continue with the
+ // for (;;) loop if something was either consumed or produced.
+ //
+ // See:
+ // - https://github.com/netty/netty/issues/4116
+ // - https://code.google.com/p/android/issues/detail?id=198639&thanks=198639&ts=1452501203
+ break;
case NOT_HANDSHAKING:
if (setHandshakeSuccessIfStillHandshaking()) {
wrapLater = true;
@@ -1179,7 +1139,7 @@
}
final CountDownLatch latch = new CountDownLatch(1);
- delegatedTaskExecutor.execute(new Runnable() {
+ delegatedTaskExecutor.execute(new OneTimeTask() {
@Override
public void run() {
try {
@@ -1283,8 +1243,7 @@
private void notifyHandshakeFailure(Throwable cause) {
if (handshakePromise.tryFailure(cause)) {
- ctx.fireUserEventTriggered(new SslHandshakeCompletionEvent(cause));
- ctx.close();
+ SslUtils.notifyHandshakeFailure(ctx, cause);
}
}
@@ -1392,6 +1351,10 @@
}
handshakePromise = p = newHandshakePromise;
+ } else if (engine.getHandshakeStatus() != HandshakeStatus.NOT_HANDSHAKING) {
+ // Not all SSLEngine implementations support calling beginHandshake multiple times while a handshake
+ // is in progress. See https://github.com/netty/netty/issues/4718.
+ return;
} else {
// Forced to reuse the old handshake.
p = handshakePromise;
@@ -1403,9 +1366,12 @@
try {
engine.beginHandshake();
wrapNonAppData(ctx, false);
- ctx.flush();
} catch (Exception e) {
notifyHandshakeFailure(e);
+ } finally {
+ // We have may haven written some parts of data before an exception was thrown so ensure we always flush.
+ // See https://github.com/netty/netty/issues/3900#issuecomment-172481830
+ ctx.flush();
}
// Set timeout if necessary.
@@ -1414,7 +1380,7 @@
return;
}
- final ScheduledFuture> timeoutFuture = ctx.executor().schedule(new Runnable() {
+ final ScheduledFuture> timeoutFuture = ctx.executor().schedule(new OneTimeTask() {
@Override
public void run() {
if (p.isDone()) {
@@ -1456,7 +1422,7 @@
final ScheduledFuture> timeoutFuture;
if (closeNotifyTimeoutMillis > 0) {
// Force-close the connection if close_notify is not fully sent in time.
- timeoutFuture = ctx.executor().schedule(new Runnable() {
+ timeoutFuture = ctx.executor().schedule(new OneTimeTask() {
@Override
public void run() {
logger.warn("{} Last write attempt timed out; force-closing the connection.", ctx.channel());
diff -Nru netty-4.0.33/handler/src/main/java/io/netty/handler/ssl/SslUtils.java netty-4.0.34/handler/src/main/java/io/netty/handler/ssl/SslUtils.java
--- netty-4.0.33/handler/src/main/java/io/netty/handler/ssl/SslUtils.java 1970-01-01 00:00:00.000000000 +0000
+++ netty-4.0.34/handler/src/main/java/io/netty/handler/ssl/SslUtils.java 2016-01-29 08:23:46.000000000 +0000
@@ -0,0 +1,127 @@
+/*
+ * Copyright 2014 The Netty Project
+ *
+ * The Netty Project licenses this file to you under the Apache License,
+ * version 2.0 (the "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+package io.netty.handler.ssl;
+
+import io.netty.buffer.ByteBuf;
+import io.netty.channel.ChannelHandlerContext;
+
+/**
+ * Constants for SSL packets.
+ */
+final class SslUtils {
+
+ /**
+ * change cipher spec
+ */
+ public static final int SSL_CONTENT_TYPE_CHANGE_CIPHER_SPEC = 20;
+
+ /**
+ * alert
+ */
+ public static final int SSL_CONTENT_TYPE_ALERT = 21;
+
+ /**
+ * handshake
+ */
+ public static final int SSL_CONTENT_TYPE_HANDSHAKE = 22;
+
+ /**
+ * application data
+ */
+ public static final int SSL_CONTENT_TYPE_APPLICATION_DATA = 23;
+
+ /**
+ * the length of the ssl record header (in bytes)
+ */
+ public static final int SSL_RECORD_HEADER_LENGTH = 5;
+
+ /**
+ * Return how much bytes can be read out of the encrypted data. Be aware that this method will not increase
+ * the readerIndex of the given {@link ByteBuf}.
+ *
+ * @param buffer
+ * The {@link ByteBuf} to read from. Be aware that it must have at least
+ * {@link #SSL_RECORD_HEADER_LENGTH} bytes to read,
+ * otherwise it will throw an {@link IllegalArgumentException}.
+ * @return length
+ * The length of the encrypted packet that is included in the buffer. This will
+ * return {@code -1} if the given {@link ByteBuf} is not encrypted at all.
+ * @throws IllegalArgumentException
+ * Is thrown if the given {@link ByteBuf} has not at least {@link #SSL_RECORD_HEADER_LENGTH}
+ * bytes to read.
+ */
+ static int getEncryptedPacketLength(ByteBuf buffer, int offset) {
+ int packetLength = 0;
+
+ // SSLv3 or TLS - Check ContentType
+ boolean tls;
+ switch (buffer.getUnsignedByte(offset)) {
+ case SSL_CONTENT_TYPE_CHANGE_CIPHER_SPEC:
+ case SSL_CONTENT_TYPE_ALERT:
+ case SSL_CONTENT_TYPE_HANDSHAKE:
+ case SSL_CONTENT_TYPE_APPLICATION_DATA:
+ tls = true;
+ break;
+ default:
+ // SSLv2 or bad data
+ tls = false;
+ }
+
+ if (tls) {
+ // SSLv3 or TLS - Check ProtocolVersion
+ int majorVersion = buffer.getUnsignedByte(offset + 1);
+ if (majorVersion == 3) {
+ // SSLv3 or TLS
+ packetLength = buffer.getUnsignedShort(offset + 3) + SSL_RECORD_HEADER_LENGTH;
+ if (packetLength <= SSL_RECORD_HEADER_LENGTH) {
+ // Neither SSLv3 or TLSv1 (i.e. SSLv2 or bad data)
+ tls = false;
+ }
+ } else {
+ // Neither SSLv3 or TLSv1 (i.e. SSLv2 or bad data)
+ tls = false;
+ }
+ }
+
+ if (!tls) {
+ // SSLv2 or bad data - Check the version
+ int headerLength = (buffer.getUnsignedByte(offset) & 0x80) != 0 ? 2 : 3;
+ int majorVersion = buffer.getUnsignedByte(offset + headerLength + 1);
+ if (majorVersion == 2 || majorVersion == 3) {
+ // SSLv2
+ if (headerLength == 2) {
+ packetLength = (buffer.getShort(offset) & 0x7FFF) + 2;
+ } else {
+ packetLength = (buffer.getShort(offset) & 0x3FFF) + 3;
+ }
+ if (packetLength <= headerLength) {
+ return -1;
+ }
+ } else {
+ return -1;
+ }
+ }
+ return packetLength;
+ }
+
+ static void notifyHandshakeFailure(ChannelHandlerContext ctx, Throwable cause) {
+ ctx.fireUserEventTriggered(new SslHandshakeCompletionEvent(cause));
+ ctx.close();
+ }
+
+ private SslUtils() {
+ }
+}
diff -Nru netty-4.0.33/handler/src/main/java/io/netty/handler/ssl/util/SelfSignedCertificate.java netty-4.0.34/handler/src/main/java/io/netty/handler/ssl/util/SelfSignedCertificate.java
--- netty-4.0.33/handler/src/main/java/io/netty/handler/ssl/util/SelfSignedCertificate.java 2015-11-03 13:18:17.000000000 +0000
+++ netty-4.0.34/handler/src/main/java/io/netty/handler/ssl/util/SelfSignedCertificate.java 2016-01-29 08:23:46.000000000 +0000
@@ -16,6 +16,7 @@
package io.netty.handler.ssl.util;
+import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.handler.codec.base64.Base64;
import io.netty.util.CharsetUtil;
@@ -162,11 +163,20 @@
certificate = new File(paths[0]);
privateKey = new File(paths[1]);
key = keypair.getPrivate();
+ FileInputStream certificateInput = null;
try {
- cert = (X509Certificate) CertificateFactory.getInstance("X509").generateCertificate(
- new FileInputStream(certificate));
+ certificateInput = new FileInputStream(certificate);
+ cert = (X509Certificate) CertificateFactory.getInstance("X509").generateCertificate(certificateInput);
} catch (Exception e) {
throw new CertificateEncodingException(e);
+ } finally {
+ if (certificateInput != null) {
+ try {
+ certificateInput.close();
+ } catch (IOException e) {
+ logger.warn("Failed to close a file: " + certificate, e);
+ }
+ }
}
}
@@ -208,11 +218,22 @@
static String[] newSelfSignedCertificate(
String fqdn, PrivateKey key, X509Certificate cert) throws IOException, CertificateEncodingException {
-
// Encode the private key into a file.
- String keyText = "-----BEGIN PRIVATE KEY-----\n" +
- Base64.encode(Unpooled.wrappedBuffer(key.getEncoded()), true).toString(CharsetUtil.US_ASCII) +
- "\n-----END PRIVATE KEY-----\n";
+ ByteBuf wrappedBuf = Unpooled.wrappedBuffer(key.getEncoded());
+ ByteBuf encodedBuf;
+ final String keyText;
+ try {
+ encodedBuf = Base64.encode(wrappedBuf, true);
+ try {
+ keyText = "-----BEGIN PRIVATE KEY-----\n" +
+ encodedBuf.toString(CharsetUtil.US_ASCII) +
+ "\n-----END PRIVATE KEY-----\n";
+ } finally {
+ encodedBuf.release();
+ }
+ } finally {
+ wrappedBuf.release();
+ }
File keyFile = File.createTempFile("keyutil_" + fqdn + '_', ".key");
keyFile.deleteOnExit();
@@ -229,10 +250,21 @@
}
}
- // Encode the certificate into a CRT file.
- String certText = "-----BEGIN CERTIFICATE-----\n" +
- Base64.encode(Unpooled.wrappedBuffer(cert.getEncoded()), true).toString(CharsetUtil.US_ASCII) +
- "\n-----END CERTIFICATE-----\n";
+ wrappedBuf = Unpooled.wrappedBuffer(cert.getEncoded());
+ final String certText;
+ try {
+ encodedBuf = Base64.encode(wrappedBuf, true);
+ try {
+ // Encode the certificate into a CRT file.
+ certText = "-----BEGIN CERTIFICATE-----\n" +
+ encodedBuf.toString(CharsetUtil.US_ASCII) +
+ "\n-----END CERTIFICATE-----\n";
+ } finally {
+ encodedBuf.release();
+ }
+ } finally {
+ wrappedBuf.release();
+ }
File certFile = File.createTempFile("keyutil_" + fqdn + '_', ".crt");
certFile.deleteOnExit();
diff -Nru netty-4.0.33/handler/src/main/java/io/netty/handler/stream/ChunkedWriteHandler.java netty-4.0.34/handler/src/main/java/io/netty/handler/stream/ChunkedWriteHandler.java
--- netty-4.0.33/handler/src/main/java/io/netty/handler/stream/ChunkedWriteHandler.java 2015-11-03 13:18:17.000000000 +0000
+++ netty-4.0.34/handler/src/main/java/io/netty/handler/stream/ChunkedWriteHandler.java 2016-01-29 08:23:46.000000000 +0000
@@ -28,6 +28,7 @@
import io.netty.channel.ChannelProgressivePromise;
import io.netty.channel.ChannelPromise;
import io.netty.util.ReferenceCountUtil;
+import io.netty.util.internal.OneTimeTask;
import io.netty.util.internal.logging.InternalLogger;
import io.netty.util.internal.logging.InternalLoggerFactory;
@@ -113,7 +114,7 @@
}
} else {
// let the transfer resume on the next event loop round
- ctx.executor().execute(new Runnable() {
+ ctx.executor().execute(new OneTimeTask() {
@Override
public void run() {
diff -Nru netty-4.0.33/handler/src/main/java/io/netty/handler/timeout/WriteTimeoutHandler.java netty-4.0.34/handler/src/main/java/io/netty/handler/timeout/WriteTimeoutHandler.java
--- netty-4.0.33/handler/src/main/java/io/netty/handler/timeout/WriteTimeoutHandler.java 2015-11-03 13:18:17.000000000 +0000
+++ netty-4.0.34/handler/src/main/java/io/netty/handler/timeout/WriteTimeoutHandler.java 2016-01-29 08:23:46.000000000 +0000
@@ -24,17 +24,16 @@
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOutboundHandlerAdapter;
import io.netty.channel.ChannelPromise;
+import io.netty.util.internal.OneTimeTask;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
/**
- * Raises a {@link WriteTimeoutException} when no data was written within a
- * certain period of time.
+ * Raises a {@link WriteTimeoutException} when a write operation cannot finish in a certain period of time.
*
*
- * // The connection is closed when there is no outbound traffic
- * // for 30 seconds.
+ * // The connection is closed when a write operation cannot finish in 30 seconds.
*
* public class MyChannelInitializer extends {@link ChannelInitializer}<{@link Channel}> {
* public void initChannel({@link Channel} channel) {
@@ -69,6 +68,11 @@
private final long timeoutNanos;
+ /**
+ * A doubly-linked list to track all WriteTimeoutTasks
+ */
+ private WriteTimeoutTask lastTask;
+
private boolean closed;
/**
@@ -107,33 +111,62 @@
ctx.write(msg, promise);
}
- private void scheduleTimeout(final ChannelHandlerContext ctx, final ChannelPromise future) {
- if (timeoutNanos > 0) {
- // Schedule a timeout.
- final ScheduledFuture> sf = ctx.executor().schedule(new Runnable() {
- @Override
- public void run() {
- // Was not written yet so issue a write timeout
- // The future itself will be failed with a ClosedChannelException once the close() was issued
- // See https://github.com/netty/netty/issues/2159
- if (!future.isDone()) {
- try {
- writeTimedOut(ctx);
- } catch (Throwable t) {
- ctx.fireExceptionCaught(t);
- }
- }
- }
- }, timeoutNanos, TimeUnit.NANOSECONDS);
+ @Override
+ public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
+ WriteTimeoutTask task = lastTask;
+ lastTask = null;
+ while (task != null) {
+ task.scheduledFuture.cancel(false);
+ WriteTimeoutTask prev = task.prev;
+ task.prev = null;
+ task.next = null;
+ task = prev;
+ }
+ }
- // Cancel the scheduled timeout if the flush future is complete.
- future.addListener(new ChannelFutureListener() {
- @Override
- public void operationComplete(ChannelFuture future) throws Exception {
- sf.cancel(false);
- }
- });
+ private void scheduleTimeout(final ChannelHandlerContext ctx, final ChannelPromise promise) {
+ // Schedule a timeout.
+ final WriteTimeoutTask task = new WriteTimeoutTask(ctx, promise);
+ task.scheduledFuture = ctx.executor().schedule(task, timeoutNanos, TimeUnit.NANOSECONDS);
+
+ if (!task.scheduledFuture.isDone()) {
+ addWriteTimeoutTask(task);
+
+ // Cancel the scheduled timeout if the flush promise is complete.
+ promise.addListener(task);
+ }
+ }
+
+ private void addWriteTimeoutTask(WriteTimeoutTask task) {
+ if (lastTask == null) {
+ lastTask = task;
+ } else {
+ lastTask.next = task;
+ task.prev = lastTask;
+ lastTask = task;
+ }
+ }
+
+ private void removeWriteTimeoutTask(WriteTimeoutTask task) {
+ if (task == lastTask) {
+ // task is the tail of list
+ assert task.next == null;
+ lastTask = lastTask.prev;
+ if (lastTask != null) {
+ lastTask.next = null;
+ }
+ } else if (task.prev == null && task.next == null) {
+ // Since task is not lastTask, then it has been removed or not been added.
+ return;
+ } else if (task.prev == null) {
+ // task is the head of list and the list has at least 2 nodes
+ task.next.prev = null;
+ } else {
+ task.prev.next = task.next;
+ task.next.prev = task.prev;
}
+ task.prev = null;
+ task.next = null;
}
/**
@@ -146,4 +179,43 @@
closed = true;
}
}
+
+ private final class WriteTimeoutTask extends OneTimeTask implements ChannelFutureListener {
+
+ private final ChannelHandlerContext ctx;
+ private final ChannelPromise promise;
+
+ // WriteTimeoutTask is also a node of a doubly-linked list
+ WriteTimeoutTask prev;
+ WriteTimeoutTask next;
+
+ ScheduledFuture> scheduledFuture;
+
+ WriteTimeoutTask(ChannelHandlerContext ctx, ChannelPromise promise) {
+ this.ctx = ctx;
+ this.promise = promise;
+ }
+
+ @Override
+ public void run() {
+ // Was not written yet so issue a write timeout
+ // The promise itself will be failed with a ClosedChannelException once the close() was issued
+ // See https://github.com/netty/netty/issues/2159
+ if (!promise.isDone()) {
+ try {
+ writeTimedOut(ctx);
+ } catch (Throwable t) {
+ ctx.fireExceptionCaught(t);
+ }
+ }
+ removeWriteTimeoutTask(this);
+ }
+
+ @Override
+ public void operationComplete(ChannelFuture future) throws Exception {
+ // scheduledFuture has already be set when reaching here
+ scheduledFuture.cancel(false);
+ removeWriteTimeoutTask(this);
+ }
+ }
}
diff -Nru netty-4.0.33/handler/src/main/java/io/netty/handler/traffic/ChannelTrafficShapingHandler.java netty-4.0.34/handler/src/main/java/io/netty/handler/traffic/ChannelTrafficShapingHandler.java
--- netty-4.0.33/handler/src/main/java/io/netty/handler/traffic/ChannelTrafficShapingHandler.java 2015-11-03 13:18:17.000000000 +0000
+++ netty-4.0.34/handler/src/main/java/io/netty/handler/traffic/ChannelTrafficShapingHandler.java 2016-01-29 08:23:46.000000000 +0000
@@ -18,6 +18,7 @@
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelPromise;
+import io.netty.util.internal.OneTimeTask;
import java.util.ArrayDeque;
import java.util.concurrent.TimeUnit;
@@ -192,7 +193,7 @@
checkWriteSuspend(ctx, delay, queueSize);
}
final long futureNow = newToSend.relativeTimeAction;
- ctx.executor().schedule(new Runnable() {
+ ctx.executor().schedule(new OneTimeTask() {
@Override
public void run() {
sendAllValid(ctx, futureNow);
diff -Nru netty-4.0.33/handler/src/main/java/io/netty/handler/traffic/GlobalTrafficShapingHandler.java netty-4.0.34/handler/src/main/java/io/netty/handler/traffic/GlobalTrafficShapingHandler.java
--- netty-4.0.33/handler/src/main/java/io/netty/handler/traffic/GlobalTrafficShapingHandler.java 2015-11-03 13:18:17.000000000 +0000
+++ netty-4.0.34/handler/src/main/java/io/netty/handler/traffic/GlobalTrafficShapingHandler.java 2016-01-29 08:23:46.000000000 +0000
@@ -21,6 +21,7 @@
import io.netty.channel.ChannelPromise;
import io.netty.channel.ChannelHandler.Sharable;
import io.netty.util.concurrent.EventExecutor;
+import io.netty.util.internal.OneTimeTask;
import io.netty.util.internal.PlatformDependent;
import java.util.ArrayDeque;
@@ -360,7 +361,7 @@
}
final long futureNow = newToSend.relativeTimeAction;
final PerChannel forSchedule = perChannel;
- ctx.executor().schedule(new Runnable() {
+ ctx.executor().schedule(new OneTimeTask() {
@Override
public void run() {
sendAllValid(ctx, forSchedule, futureNow);
diff -Nru netty-4.0.33/handler/src/test/java/io/netty/handler/ssl/JdkSslEngineTest.java netty-4.0.34/handler/src/test/java/io/netty/handler/ssl/JdkSslEngineTest.java
--- netty-4.0.33/handler/src/test/java/io/netty/handler/ssl/JdkSslEngineTest.java 2015-11-03 13:18:17.000000000 +0000
+++ netty-4.0.34/handler/src/test/java/io/netty/handler/ssl/JdkSslEngineTest.java 2016-01-29 08:23:46.000000000 +0000
@@ -15,37 +15,24 @@
*/
package io.netty.handler.ssl;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assume.assumeNoException;
-import io.netty.bootstrap.Bootstrap;
-import io.netty.bootstrap.ServerBootstrap;
-import io.netty.channel.Channel;
-import io.netty.channel.ChannelFuture;
-import io.netty.channel.ChannelHandlerAdapter;
-import io.netty.channel.ChannelHandlerContext;
-import io.netty.channel.ChannelInitializer;
-import io.netty.channel.ChannelPipeline;
-import io.netty.channel.nio.NioEventLoopGroup;
-import io.netty.channel.socket.nio.NioServerSocketChannel;
-import io.netty.channel.socket.nio.NioSocketChannel;
+import io.netty.handler.ssl.ApplicationProtocolConfig.Protocol;
+import io.netty.handler.ssl.ApplicationProtocolConfig.SelectedListenerFailureBehavior;
+import io.netty.handler.ssl.ApplicationProtocolConfig.SelectorFailureBehavior;
import io.netty.handler.ssl.JdkApplicationProtocolNegotiator.ProtocolSelector;
import io.netty.handler.ssl.JdkApplicationProtocolNegotiator.ProtocolSelectorFactory;
import io.netty.handler.ssl.util.InsecureTrustManagerFactory;
import io.netty.handler.ssl.util.SelfSignedCertificate;
-import io.netty.util.NetUtil;
+import org.junit.Test;
-import java.net.InetSocketAddress;
-import java.security.cert.CertificateException;
+import javax.net.ssl.SSLEngine;
+import javax.net.ssl.SSLHandshakeException;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;
-import javax.net.ssl.SSLEngine;
-import javax.net.ssl.SSLException;
-import javax.net.ssl.SSLHandshakeException;
-
-import org.junit.Test;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeNoException;
public class JdkSslEngineTest extends SSLEngineTest {
private static final String PREFERRED_APPLICATION_LEVEL_PROTOCOL = "my-protocol-http2";
@@ -59,13 +46,13 @@
// Check in this test just in case we have multiple tests that just the class and we already ignored the
// initialization error.
if (!JdkNpnSslEngine.isAvailable()) {
- throw new RuntimeException("NPN not on classpath");
+ throw tlsExtensionNotFound(Protocol.NPN);
}
- JdkApplicationProtocolNegotiator apn = new JdkNpnApplicationProtocolNegotiator(true, true,
+ ApplicationProtocolConfig apn = failingNegotiator(Protocol.NPN,
PREFERRED_APPLICATION_LEVEL_PROTOCOL);
- mySetup(apn);
+ setupHandlers(apn);
runTest();
- } catch (RuntimeException e) {
+ } catch (SkipTestException e) {
// NPN availability is dependent on the java version. If NPN is not available because of
// java version incompatibility don't fail the test, but instead just skip the test
assumeNoException(e);
@@ -79,15 +66,15 @@
// Check in this test just in case we have multiple tests that just the class and we already ignored the
// initialization error.
if (!JdkNpnSslEngine.isAvailable()) {
- throw new RuntimeException("NPN not on classpath");
+ throw tlsExtensionNotFound(Protocol.NPN);
}
- JdkApplicationProtocolNegotiator clientApn = new JdkNpnApplicationProtocolNegotiator(false, false,
+ ApplicationProtocolConfig clientApn = acceptingNegotiator(Protocol.NPN,
PREFERRED_APPLICATION_LEVEL_PROTOCOL);
- JdkApplicationProtocolNegotiator serverApn = new JdkNpnApplicationProtocolNegotiator(false, false,
+ ApplicationProtocolConfig serverApn = acceptingNegotiator(Protocol.NPN,
APPLICATION_LEVEL_PROTOCOL_NOT_COMPATIBLE);
- mySetup(serverApn, clientApn);
+ setupHandlers(serverApn, clientApn);
runTest(null);
- } catch (Exception e) {
+ } catch (SkipTestException e) {
// ALPN availability is dependent on the java version. If ALPN is not available because of
// java version incompatibility don't fail the test, but instead just skip the test
assumeNoException(e);
@@ -101,16 +88,16 @@
// Check in this test just in case we have multiple tests that just the class and we already ignored the
// initialization error.
if (!JdkNpnSslEngine.isAvailable()) {
- throw new RuntimeException("NPN not on classpath");
+ throw tlsExtensionNotFound(Protocol.NPN);
}
- JdkApplicationProtocolNegotiator clientApn = new JdkNpnApplicationProtocolNegotiator(true, true,
+ ApplicationProtocolConfig clientApn = failingNegotiator(Protocol.NPN,
PREFERRED_APPLICATION_LEVEL_PROTOCOL);
- JdkApplicationProtocolNegotiator serverApn = new JdkNpnApplicationProtocolNegotiator(false, false,
+ ApplicationProtocolConfig serverApn = acceptingNegotiator(Protocol.NPN,
APPLICATION_LEVEL_PROTOCOL_NOT_COMPATIBLE);
- mySetup(serverApn, clientApn);
+ setupHandlers(serverApn, clientApn);
assertTrue(clientLatch.await(2, TimeUnit.SECONDS));
assertTrue(clientException instanceof SSLHandshakeException);
- } catch (RuntimeException e) {
+ } catch (SkipTestException e) {
// NPN availability is dependent on the java version. If NPN is not available because of
// java version incompatibility don't fail the test, but instead just skip the test
assumeNoException(e);
@@ -124,16 +111,16 @@
// Check in this test just in case we have multiple tests that just the class and we already ignored the
// initialization error.
if (!JdkNpnSslEngine.isAvailable()) {
- throw new RuntimeException("NPN not on classpath");
+ throw tlsExtensionNotFound(Protocol.NPN);
}
- JdkApplicationProtocolNegotiator clientApn = new JdkNpnApplicationProtocolNegotiator(false, false,
+ ApplicationProtocolConfig clientApn = acceptingNegotiator(Protocol.NPN,
PREFERRED_APPLICATION_LEVEL_PROTOCOL);
- JdkApplicationProtocolNegotiator serverApn = new JdkNpnApplicationProtocolNegotiator(true, true,
+ ApplicationProtocolConfig serverApn = failingNegotiator(Protocol.NPN,
APPLICATION_LEVEL_PROTOCOL_NOT_COMPATIBLE);
- mySetup(serverApn, clientApn);
+ setupHandlers(serverApn, clientApn);
assertTrue(serverLatch.await(2, TimeUnit.SECONDS));
assertTrue(serverException instanceof SSLHandshakeException);
- } catch (RuntimeException e) {
+ } catch (SkipTestException e) {
// NPN availability is dependent on the java version. If NPN is not available because of
// java version incompatibility don't fail the test, but instead just skip the test
assumeNoException(e);
@@ -147,13 +134,13 @@
// Check in this test just in case we have multiple tests that just the class and we already ignored the
// initialization error.
if (!JdkAlpnSslEngine.isAvailable()) {
- throw new RuntimeException("ALPN not on classpath");
+ throw tlsExtensionNotFound(Protocol.ALPN);
}
- JdkApplicationProtocolNegotiator apn = new JdkAlpnApplicationProtocolNegotiator(true, true,
+ ApplicationProtocolConfig apn = failingNegotiator(Protocol.ALPN,
PREFERRED_APPLICATION_LEVEL_PROTOCOL);
- mySetup(apn);
+ setupHandlers(apn);
runTest();
- } catch (Exception e) {
+ } catch (SkipTestException e) {
// ALPN availability is dependent on the java version. If ALPN is not available because of
// java version incompatibility don't fail the test, but instead just skip the test
assumeNoException(e);
@@ -167,15 +154,15 @@
// Check in this test just in case we have multiple tests that just the class and we already ignored the
// initialization error.
if (!JdkAlpnSslEngine.isAvailable()) {
- throw new RuntimeException("ALPN not on classpath");
+ throw tlsExtensionNotFound(Protocol.ALPN);
}
- JdkApplicationProtocolNegotiator clientApn = new JdkAlpnApplicationProtocolNegotiator(false, false,
+ ApplicationProtocolConfig clientApn = acceptingNegotiator(Protocol.ALPN,
PREFERRED_APPLICATION_LEVEL_PROTOCOL);
- JdkApplicationProtocolNegotiator serverApn = new JdkAlpnApplicationProtocolNegotiator(false, false,
+ ApplicationProtocolConfig serverApn = acceptingNegotiator(Protocol.ALPN,
APPLICATION_LEVEL_PROTOCOL_NOT_COMPATIBLE);
- mySetup(serverApn, clientApn);
+ setupHandlers(serverApn, clientApn);
runTest(null);
- } catch (Exception e) {
+ } catch (SkipTestException e) {
// ALPN availability is dependent on the java version. If ALPN is not available because of
// java version incompatibility don't fail the test, but instead just skip the test
assumeNoException(e);
@@ -189,16 +176,16 @@
// Check in this test just in case we have multiple tests that just the class and we already ignored the
// initialization error.
if (!JdkAlpnSslEngine.isAvailable()) {
- throw new RuntimeException("ALPN not on classpath");
+ throw tlsExtensionNotFound(Protocol.ALPN);
}
- JdkApplicationProtocolNegotiator clientApn = new JdkAlpnApplicationProtocolNegotiator(false, false,
+ ApplicationProtocolConfig clientApn = acceptingNegotiator(Protocol.ALPN,
PREFERRED_APPLICATION_LEVEL_PROTOCOL);
- JdkApplicationProtocolNegotiator serverApn = new JdkAlpnApplicationProtocolNegotiator(true, true,
+ ApplicationProtocolConfig serverApn = failingNegotiator(Protocol.ALPN,
APPLICATION_LEVEL_PROTOCOL_NOT_COMPATIBLE);
- mySetup(serverApn, clientApn);
+ setupHandlers(serverApn, clientApn);
assertTrue(serverLatch.await(2, TimeUnit.SECONDS));
assertTrue(serverException instanceof SSLHandshakeException);
- } catch (Exception e) {
+ } catch (SkipTestException e) {
// ALPN availability is dependent on the java version. If ALPN is not available because of
// java version incompatibility don't fail the test, but instead just skip the test
assumeNoException(e);
@@ -212,18 +199,18 @@
// Check in this test just in case we have multiple tests that just the class and we already ignored the
// initialization error.
if (!JdkAlpnSslEngine.isAvailable()) {
- throw new RuntimeException("ALPN not on classpath");
+ throw tlsExtensionNotFound(Protocol.ALPN);
}
// Even the preferred application protocol appears second in the client's list, it will be picked
// because it's the first one on server's list.
- JdkApplicationProtocolNegotiator clientApn = new JdkAlpnApplicationProtocolNegotiator(false, false,
+ ApplicationProtocolConfig clientApn = acceptingNegotiator(Protocol.ALPN,
FALLBACK_APPLICATION_LEVEL_PROTOCOL, PREFERRED_APPLICATION_LEVEL_PROTOCOL);
- JdkApplicationProtocolNegotiator serverApn = new JdkAlpnApplicationProtocolNegotiator(true, true,
+ ApplicationProtocolConfig serverApn = failingNegotiator(Protocol.ALPN,
PREFERRED_APPLICATION_LEVEL_PROTOCOL, FALLBACK_APPLICATION_LEVEL_PROTOCOL);
- mySetup(serverApn, clientApn);
+ setupHandlers(serverApn, clientApn);
assertNull(serverException);
runTest(PREFERRED_APPLICATION_LEVEL_PROTOCOL);
- } catch (Exception e) {
+ } catch (SkipTestException e) {
// ALPN availability is dependent on the java version. If ALPN is not available because of
// java version incompatibility don't fail the test, but instead just skip the test
assumeNoException(e);
@@ -237,8 +224,9 @@
// Check in this test just in case we have multiple tests that just the class and we already ignored the
// initialization error.
if (!JdkAlpnSslEngine.isAvailable()) {
- throw new RuntimeException("ALPN not on classpath");
+ throw tlsExtensionNotFound(Protocol.ALPN);
}
+ SelfSignedCertificate ssc = new SelfSignedCertificate();
JdkApplicationProtocolNegotiator clientApn = new JdkAlpnApplicationProtocolNegotiator(true, true,
PREFERRED_APPLICATION_LEVEL_PROTOCOL);
JdkApplicationProtocolNegotiator serverApn = new JdkAlpnApplicationProtocolNegotiator(
@@ -258,84 +246,25 @@
}
}, JdkBaseApplicationProtocolNegotiator.FAIL_SELECTION_LISTENER_FACTORY,
APPLICATION_LEVEL_PROTOCOL_NOT_COMPATIBLE);
- mySetup(serverApn, clientApn);
+
+ SslContext serverSslCtx = new JdkSslServerContext(ssc.certificate(), ssc.privateKey(), null, null,
+ IdentityCipherSuiteFilter.INSTANCE, serverApn, 0, 0);
+ SslContext clientSslCtx = new JdkSslClientContext(null, InsecureTrustManagerFactory.INSTANCE, null,
+ IdentityCipherSuiteFilter.INSTANCE, clientApn, 0, 0);
+
+ setupHandlers(serverSslCtx, clientSslCtx);
assertTrue(clientLatch.await(2, TimeUnit.SECONDS));
assertTrue(clientException instanceof SSLHandshakeException);
- } catch (Exception e) {
+ } catch (SkipTestException e) {
// ALPN availability is dependent on the java version. If ALPN is not available because of
// java version incompatibility don't fail the test, but instead just skip the test
assumeNoException(e);
}
}
- private void mySetup(JdkApplicationProtocolNegotiator apn) throws InterruptedException, SSLException,
- CertificateException {
- mySetup(apn, apn);
- }
-
- private void mySetup(JdkApplicationProtocolNegotiator serverApn, JdkApplicationProtocolNegotiator clientApn)
- throws InterruptedException, SSLException, CertificateException {
- SelfSignedCertificate ssc = new SelfSignedCertificate();
- serverSslCtx = new JdkSslServerContext(ssc.certificate(), ssc.privateKey(), null, null,
- IdentityCipherSuiteFilter.INSTANCE, serverApn, 0, 0);
- clientSslCtx = new JdkSslClientContext(null, InsecureTrustManagerFactory.INSTANCE, null,
- IdentityCipherSuiteFilter.INSTANCE, clientApn, 0, 0);
-
- serverConnectedChannel = null;
- sb = new ServerBootstrap();
- cb = new Bootstrap();
-
- sb.group(new NioEventLoopGroup(), new NioEventLoopGroup());
- sb.channel(NioServerSocketChannel.class);
- sb.childHandler(new ChannelInitializer() {
- @Override
- protected void initChannel(Channel ch) throws Exception {
- ChannelPipeline p = ch.pipeline();
- p.addLast(serverSslCtx.newHandler(ch.alloc()));
- p.addLast(new MessageDelegatorChannelHandler(serverReceiver, serverLatch));
- p.addLast(new ChannelHandlerAdapter() {
- @Override
- public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
- if (cause.getCause() instanceof SSLHandshakeException) {
- serverException = cause.getCause();
- serverLatch.countDown();
- } else {
- ctx.fireExceptionCaught(cause);
- }
- }
- });
- serverConnectedChannel = ch;
- }
- });
-
- cb.group(new NioEventLoopGroup());
- cb.channel(NioSocketChannel.class);
- cb.handler(new ChannelInitializer() {
- @Override
- protected void initChannel(Channel ch) throws Exception {
- ChannelPipeline p = ch.pipeline();
- p.addLast(clientSslCtx.newHandler(ch.alloc()));
- p.addLast(new MessageDelegatorChannelHandler(clientReceiver, clientLatch));
- p.addLast(new ChannelHandlerAdapter() {
- @Override
- public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
- if (cause.getCause() instanceof SSLHandshakeException) {
- clientException = cause.getCause();
- clientLatch.countDown();
- } else {
- ctx.fireExceptionCaught(cause);
- }
- }
- });
- }
- });
-
- serverChannel = sb.bind(new InetSocketAddress(0)).sync().channel();
- int port = ((InetSocketAddress) serverChannel.localAddress()).getPort();
-
- ChannelFuture ccf = cb.connect(new InetSocketAddress(NetUtil.LOCALHOST, port));
- assertTrue(ccf.awaitUninterruptibly().isSuccess());
- clientChannel = ccf.channel();
+ @Test
+ public void testEnablingAnAlreadyDisabledSslProtocol() throws Exception {
+ testEnablingAnAlreadyDisabledSslProtocol(new String[]{}, new String[]{PROTOCOL_TLS_V1_2});
}
private void runTest() throws Exception {
@@ -346,4 +275,30 @@
protected SslProvider sslProvider() {
return SslProvider.JDK;
}
+
+ private ApplicationProtocolConfig failingNegotiator(Protocol protocol,
+ String... supportedProtocols) {
+ return new ApplicationProtocolConfig(protocol,
+ SelectorFailureBehavior.FATAL_ALERT,
+ SelectedListenerFailureBehavior.FATAL_ALERT,
+ supportedProtocols);
+ }
+
+ private ApplicationProtocolConfig acceptingNegotiator(Protocol protocol,
+ String... supportedProtocols) {
+ return new ApplicationProtocolConfig(protocol,
+ SelectorFailureBehavior.NO_ADVERTISE,
+ SelectedListenerFailureBehavior.ACCEPT,
+ supportedProtocols);
+ }
+
+ private SkipTestException tlsExtensionNotFound(Protocol protocol) {
+ throw new SkipTestException(protocol + " not on classpath");
+ }
+
+ private static final class SkipTestException extends RuntimeException {
+ public SkipTestException(String message) {
+ super(message);
+ }
+ }
}
diff -Nru netty-4.0.33/handler/src/test/java/io/netty/handler/ssl/OpenSslEngineTest.java netty-4.0.34/handler/src/test/java/io/netty/handler/ssl/OpenSslEngineTest.java
--- netty-4.0.33/handler/src/test/java/io/netty/handler/ssl/OpenSslEngineTest.java 2015-11-03 13:18:17.000000000 +0000
+++ netty-4.0.34/handler/src/test/java/io/netty/handler/ssl/OpenSslEngineTest.java 2016-01-29 08:23:46.000000000 +0000
@@ -15,9 +15,58 @@
*/
package io.netty.handler.ssl;
+import org.junit.Test;
+
+import io.netty.handler.ssl.ApplicationProtocolConfig.Protocol;
+import io.netty.handler.ssl.ApplicationProtocolConfig.SelectedListenerFailureBehavior;
+import io.netty.handler.ssl.ApplicationProtocolConfig.SelectorFailureBehavior;
+
+import static org.junit.Assert.assertNull;
import static org.junit.Assume.assumeTrue;
public class OpenSslEngineTest extends SSLEngineTest {
+ private static final String PREFERRED_APPLICATION_LEVEL_PROTOCOL = "my-protocol-http2";
+ private static final String FALLBACK_APPLICATION_LEVEL_PROTOCOL = "my-protocol-http1_1";
+
+ @Test
+ public void testNpn() throws Exception {
+ assumeTrue(OpenSsl.isAvailable());
+ ApplicationProtocolConfig apn = acceptingNegotiator(Protocol.NPN,
+ PREFERRED_APPLICATION_LEVEL_PROTOCOL);
+ setupHandlers(apn);
+ runTest(PREFERRED_APPLICATION_LEVEL_PROTOCOL);
+ }
+
+ @Test
+ public void testAlpn() throws Exception {
+ assumeTrue(OpenSsl.isAvailable());
+ assumeTrue(OpenSsl.isAlpnSupported());
+ ApplicationProtocolConfig apn = acceptingNegotiator(Protocol.ALPN,
+ PREFERRED_APPLICATION_LEVEL_PROTOCOL);
+ setupHandlers(apn);
+ runTest(PREFERRED_APPLICATION_LEVEL_PROTOCOL);
+ }
+
+ @Test
+ public void testAlpnCompatibleProtocolsDifferentClientOrder() throws Exception {
+ assumeTrue(OpenSsl.isAvailable());
+ assumeTrue(OpenSsl.isAlpnSupported());
+ ApplicationProtocolConfig clientApn = acceptingNegotiator(Protocol.ALPN,
+ FALLBACK_APPLICATION_LEVEL_PROTOCOL, PREFERRED_APPLICATION_LEVEL_PROTOCOL);
+ ApplicationProtocolConfig serverApn = acceptingNegotiator(Protocol.ALPN,
+ PREFERRED_APPLICATION_LEVEL_PROTOCOL, FALLBACK_APPLICATION_LEVEL_PROTOCOL);
+ setupHandlers(serverApn, clientApn);
+ assertNull(serverException);
+ runTest(PREFERRED_APPLICATION_LEVEL_PROTOCOL);
+ }
+
+ @Test
+ public void testEnablingAnAlreadyDisabledSslProtocol() throws Exception {
+ assumeTrue(OpenSsl.isAvailable());
+ testEnablingAnAlreadyDisabledSslProtocol(new String[]{PROTOCOL_SSL_V2_HELLO},
+ new String[]{PROTOCOL_SSL_V2_HELLO, PROTOCOL_TLS_V1_2});
+ }
+
@Override
public void testMutualAuthSameCerts() throws Exception {
assumeTrue(OpenSsl.isAvailable());
@@ -58,4 +107,12 @@
protected SslProvider sslProvider() {
return SslProvider.OPENSSL;
}
+
+ private static ApplicationProtocolConfig acceptingNegotiator(Protocol protocol,
+ String... supportedProtocols) {
+ return new ApplicationProtocolConfig(protocol,
+ SelectorFailureBehavior.NO_ADVERTISE,
+ SelectedListenerFailureBehavior.ACCEPT,
+ supportedProtocols);
+ }
}
diff -Nru netty-4.0.33/handler/src/test/java/io/netty/handler/ssl/SniHandlerTest.java netty-4.0.34/handler/src/test/java/io/netty/handler/ssl/SniHandlerTest.java
--- netty-4.0.33/handler/src/test/java/io/netty/handler/ssl/SniHandlerTest.java 2015-11-03 13:18:17.000000000 +0000
+++ netty-4.0.34/handler/src/test/java/io/netty/handler/ssl/SniHandlerTest.java 2016-01-29 08:23:46.000000000 +0000
@@ -34,7 +34,7 @@
File keyFile = new File(SniHandlerTest.class.getResource("test_encrypted.pem").getFile());
File crtFile = new File(SniHandlerTest.class.getResource("test.crt").getFile());
- return new JdkSslServerContext(crtFile, keyFile, "12345");
+ return SslContextBuilder.forServer(crtFile, keyFile, "12345").build();
}
@Test
diff -Nru netty-4.0.33/handler/src/test/java/io/netty/handler/ssl/SSLEngineTest.java netty-4.0.34/handler/src/test/java/io/netty/handler/ssl/SSLEngineTest.java
--- netty-4.0.33/handler/src/test/java/io/netty/handler/ssl/SSLEngineTest.java 2015-11-03 13:18:17.000000000 +0000
+++ netty-4.0.34/handler/src/test/java/io/netty/handler/ssl/SSLEngineTest.java 2016-01-29 08:23:46.000000000 +0000
@@ -22,8 +22,8 @@
import io.netty.buffer.UnpooledByteBufAllocator;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
-import io.netty.channel.ChannelHandlerAdapter;
import io.netty.channel.ChannelHandlerContext;
+import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.SimpleChannelInboundHandler;
@@ -49,6 +49,7 @@
import java.io.File;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
+import java.security.cert.CertificateException;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
@@ -58,10 +59,13 @@
public abstract class SSLEngineTest {
+ protected static final String PROTOCOL_TLS_V1_2 = "TLSv1.2";
+ protected static final String PROTOCOL_SSL_V2_HELLO = "SSLv2Hello";
+
@Mock
- protected MessageReciever serverReceiver;
+ protected MessageReceiver serverReceiver;
@Mock
- protected MessageReciever clientReceiver;
+ protected MessageReceiver clientReceiver;
protected Throwable serverException;
protected Throwable clientException;
@@ -75,15 +79,15 @@
protected CountDownLatch serverLatch;
protected CountDownLatch clientLatch;
- interface MessageReciever {
+ interface MessageReceiver {
void messageReceived(ByteBuf msg);
}
protected static final class MessageDelegatorChannelHandler extends SimpleChannelInboundHandler {
- private final MessageReciever receiver;
+ private final MessageReceiver receiver;
private final CountDownLatch latch;
- public MessageDelegatorChannelHandler(MessageReciever receiver, CountDownLatch latch) {
+ public MessageDelegatorChannelHandler(MessageReceiver receiver, CountDownLatch latch) {
super(false);
this.receiver = receiver;
this.latch = latch;
@@ -180,13 +184,22 @@
File servertTrustCrtFile, File serverKeyFile, File serverCrtFile, String serverKeyPassword,
File clientTrustCrtFile, File clientKeyFile, File clientCrtFile, String clientKeyPassword)
throws InterruptedException, SSLException {
- serverSslCtx = SslContext.newServerContext(sslProvider(), servertTrustCrtFile, null,
- serverCrtFile, serverKeyFile, serverKeyPassword, null,
- null, IdentityCipherSuiteFilter.INSTANCE, null, 0, 0);
- clientSslCtx = SslContext.newClientContext(sslProvider(), clientTrustCrtFile, null,
- clientCrtFile, clientKeyFile, clientKeyPassword, null,
- null, IdentityCipherSuiteFilter.INSTANCE,
- null, 0, 0);
+ serverSslCtx = SslContextBuilder.forServer(serverCrtFile, serverKeyFile, serverKeyPassword)
+ .sslProvider(sslProvider())
+ .trustManager(servertTrustCrtFile)
+ .ciphers(null, IdentityCipherSuiteFilter.INSTANCE)
+ .sessionCacheSize(0)
+ .sessionTimeout(0)
+ .build();
+
+ clientSslCtx = SslContextBuilder.forClient()
+ .sslProvider(sslProvider())
+ .trustManager(clientTrustCrtFile)
+ .keyManager(clientCrtFile, clientKeyFile, clientKeyPassword)
+ .ciphers(null, IdentityCipherSuiteFilter.INSTANCE)
+ .sessionCacheSize(0)
+ .sessionTimeout(0)
+ .build();
serverConnectedChannel = null;
sb = new ServerBootstrap();
@@ -203,7 +216,7 @@
engine.setNeedClientAuth(true);
p.addLast(new SslHandler(engine));
p.addLast(new MessageDelegatorChannelHandler(serverReceiver, serverLatch));
- p.addLast(new ChannelHandlerAdapter() {
+ p.addLast(new ChannelInboundHandlerAdapter() {
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
if (cause.getCause() instanceof SSLHandshakeException) {
@@ -226,7 +239,7 @@
ChannelPipeline p = ch.pipeline();
p.addLast(clientSslCtx.newHandler(ch.alloc()));
p.addLast(new MessageDelegatorChannelHandler(clientReceiver, clientLatch));
- p.addLast(new ChannelHandlerAdapter() {
+ p.addLast(new ChannelInboundHandlerAdapter() {
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
cause.printStackTrace();
@@ -273,7 +286,7 @@
}
private static void writeAndVerifyReceived(ByteBuf message, Channel sendChannel, CountDownLatch receiverLatch,
- MessageReciever receiver) throws Exception {
+ MessageReceiver receiver) throws Exception {
List dataCapture = null;
try {
sendChannel.writeAndFlush(message);
@@ -319,6 +332,40 @@
assertFalse(session.isValid());
}
+ protected void testEnablingAnAlreadyDisabledSslProtocol(String[] protocols1, String[] protocols2) throws Exception {
+ SSLEngine sslEngine = null;
+ try {
+ File serverKeyFile = new File(getClass().getResource("test_unencrypted.pem").getFile());
+ File serverCrtFile = new File(getClass().getResource("test.crt").getFile());
+ SslContext sslContext = SslContextBuilder.forServer(serverCrtFile, serverKeyFile)
+ .sslProvider(sslProvider())
+ .build();
+
+ sslEngine = sslContext.newEngine(UnpooledByteBufAllocator.DEFAULT);
+
+ // Disable all protocols
+ sslEngine.setEnabledProtocols(new String[]{});
+
+ // The only protocol that should be enabled is SSLv2Hello
+ String[] enabledProtocols = sslEngine.getEnabledProtocols();
+ assertEquals(protocols1.length, enabledProtocols.length);
+ assertArrayEquals(protocols1, enabledProtocols);
+
+ // Enable a protocol that is currently disabled
+ sslEngine.setEnabledProtocols(new String[]{PROTOCOL_TLS_V1_2});
+
+ // The protocol that was just enabled should be returned
+ enabledProtocols = sslEngine.getEnabledProtocols();
+ assertEquals(protocols2.length, enabledProtocols.length);
+ assertArrayEquals(protocols2, enabledProtocols);
+ } finally {
+ if (sslEngine != null) {
+ sslEngine.closeInbound();
+ sslEngine.closeOutbound();
+ }
+ }
+ }
+
private static void handshake(SSLEngine clientEngine, SSLEngine serverEngine) throws SSLException {
int netBufferSize = 17 * 1024;
ByteBuffer cTOs = ByteBuffer.allocateDirect(netBufferSize);
@@ -350,7 +397,7 @@
runDelegatedTasks(serverResult, serverEngine);
cTOs.compact();
sTOc.compact();
- } while (isHandshaking(clientResult) && isHandshaking(serverResult));
+ } while (isHandshaking(clientResult) || isHandshaking(serverResult));
}
private static boolean isHandshaking(SSLEngineResult result) {
@@ -371,4 +418,94 @@
}
protected abstract SslProvider sslProvider();
+
+ protected void setupHandlers(ApplicationProtocolConfig apn) throws InterruptedException, SSLException,
+ CertificateException {
+ setupHandlers(apn, apn);
+ }
+
+ protected void setupHandlers(ApplicationProtocolConfig serverApn, ApplicationProtocolConfig clientApn)
+ throws InterruptedException, SSLException, CertificateException {
+ SelfSignedCertificate ssc = new SelfSignedCertificate();
+
+ setupHandlers(SslContextBuilder.forServer(ssc.certificate(), ssc.privateKey(), null)
+ .sslProvider(sslProvider())
+ .ciphers(null, IdentityCipherSuiteFilter.INSTANCE)
+ .applicationProtocolConfig(serverApn)
+ .sessionCacheSize(0)
+ .sessionTimeout(0)
+ .build(),
+
+ SslContextBuilder.forClient()
+ .sslProvider(sslProvider())
+ .applicationProtocolConfig(clientApn)
+ .trustManager(InsecureTrustManagerFactory.INSTANCE)
+ .ciphers(null, IdentityCipherSuiteFilter.INSTANCE)
+ .sessionCacheSize(0)
+ .sessionTimeout(0)
+ .build());
+ }
+
+ protected void setupHandlers(SslContext serverCtx, SslContext clientCtx)
+ throws InterruptedException, SSLException, CertificateException {
+
+ serverSslCtx = serverCtx;
+ clientSslCtx = clientCtx;
+
+ serverConnectedChannel = null;
+ sb = new ServerBootstrap();
+ cb = new Bootstrap();
+
+ sb.group(new NioEventLoopGroup(), new NioEventLoopGroup());
+ sb.channel(NioServerSocketChannel.class);
+ sb.childHandler(new ChannelInitializer() {
+ @Override
+ protected void initChannel(Channel ch) throws Exception {
+ ChannelPipeline p = ch.pipeline();
+ p.addLast(serverSslCtx.newHandler(ch.alloc()));
+ p.addLast(new MessageDelegatorChannelHandler(serverReceiver, serverLatch));
+ p.addLast(new ChannelInboundHandlerAdapter() {
+ @Override
+ public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
+ if (cause.getCause() instanceof SSLHandshakeException) {
+ serverException = cause.getCause();
+ serverLatch.countDown();
+ } else {
+ ctx.fireExceptionCaught(cause);
+ }
+ }
+ });
+ serverConnectedChannel = ch;
+ }
+ });
+
+ cb.group(new NioEventLoopGroup());
+ cb.channel(NioSocketChannel.class);
+ cb.handler(new ChannelInitializer() {
+ @Override
+ protected void initChannel(Channel ch) throws Exception {
+ ChannelPipeline p = ch.pipeline();
+ p.addLast(clientSslCtx.newHandler(ch.alloc()));
+ p.addLast(new MessageDelegatorChannelHandler(clientReceiver, clientLatch));
+ p.addLast(new ChannelInboundHandlerAdapter() {
+ @Override
+ public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
+ if (cause.getCause() instanceof SSLHandshakeException) {
+ clientException = cause.getCause();
+ clientLatch.countDown();
+ } else {
+ ctx.fireExceptionCaught(cause);
+ }
+ }
+ });
+ }
+ });
+
+ serverChannel = sb.bind(new InetSocketAddress(0)).syncUninterruptibly().channel();
+
+ ChannelFuture ccf = cb.connect(serverChannel.localAddress());
+ assertTrue(ccf.syncUninterruptibly().isSuccess());
+ clientChannel = ccf.channel();
+ }
+
}
diff -Nru netty-4.0.33/microbench/pom.xml netty-4.0.34/microbench/pom.xml
--- netty-4.0.33/microbench/pom.xml 2015-11-03 13:18:17.000000000 +0000
+++ netty-4.0.34/microbench/pom.xml 2016-01-29 08:23:46.000000000 +0000
@@ -20,7 +20,7 @@
io.nettynetty-parent
- 4.0.33.Final
+ 4.0.34.Finalnetty-microbench
diff -Nru netty-4.0.33/pom.xml netty-4.0.34/pom.xml
--- netty-4.0.33/pom.xml 2015-11-03 13:18:17.000000000 +0000
+++ netty-4.0.34/pom.xml 2016-01-29 08:23:46.000000000 +0000
@@ -26,7 +26,7 @@
io.nettynetty-parentpom
- 4.0.33.Final
+ 4.0.34.FinalNettyhttp://netty.io/
@@ -53,7 +53,7 @@
https://github.com/netty/nettyscm:git:git://github.com/netty/netty.gitscm:git:ssh://git@github.com/netty/netty.git
- netty-4.0.33.Final
+ netty-4.0.34.Final
@@ -122,7 +122,7 @@
-
- alpn-7latest
-
- [1.7,1.8)
-
-
- 7.1.3.v20150130
-
-
-
- npn-latest
-
-
- [1.7,)
-
-
- 1.1.11.v20150415
-
-
-
- alpn-8latest
-
- [1.8,)
-
-
- 8.1.4.v20150727
-
-
-
- npn-7u9
-
-
- java.version
- 1.7.0_9
-
-
-
- 1.1.3.v20130313
-
-
-
- npn-7u10
-
-
- java.version
- 1.7.0_10
-
-
-
- 1.1.3.v20130313
-
-
-
- npn-7u11
-
-
- java.version
- 1.7.0_11
-
-
-
- 1.1.3.v20130313
-
-
-
- npn-7u13
-
-
- java.version
- 1.7.0_13
-
-
-
- 1.1.4.v20130313
-
-
-
- npn-7u15
-
-
- java.version
- 1.7.0_15
-
-
-
- 1.1.5.v20130313
-
-
-
- npn-7u17
-
-
- java.version
- 1.7.0_17
-
-
-
- 1.1.5.v20130313
-
-
-
- npn-7u21
-
-
- java.version
- 1.7.0_21
-
-
-
- 1.1.5.v20130313
-
-
-
- npn-7u25
-
-
- java.version
- 1.7.0_25
-
-
-
- 1.1.5.v20130313
-
-
-
- npn-alpn-7u40
-
-
- java.version
- 1.7.0_40
-
-
-
- 1.1.6.v20130911
- 7.1.0.v20141016
-
-
-
- npn-alpn-7u45
-
-
- java.version
- 1.7.0_45
-
-
-
- 1.1.6.v20130911
- 7.1.0.v20141016
-
-
-
- npn-alpn-7u51
-
-
- java.version
- 1.7.0_51
-
-
-
- 1.1.6.v20130911
- 7.1.0.v20141016
-
-
-
- npn-alpn-7u55
-
-
- java.version
- 1.7.0_55
-
-
-
- 1.1.8.v20141013
- 7.1.0.v20141016
-
-
-
- npn-alpn-7u60
-
-
- java.version
- 1.7.0_60
-
-
-
- 1.1.8.v20141013
- 7.1.0.v20141016
-
-
-
- npn-alpn-7u65
-
-
- java.version
- 1.7.0_65
-
-
-
- 1.1.8.v20141013
- 7.1.0.v20141016
-
-
-
- npn-alpn-7u67
-
-
- java.version
- 1.7.0_67
-
-
-
- 1.1.8.v20141013
- 7.1.0.v20141016
-
-
-
- npn-alpn-7u71
-
-
- java.version
- 1.7.0_71
-
-
-
- 1.1.9.v20141016
- 7.1.2.v20141202
-
-
-
- npn-alpn-7u72
-
-
- java.version
- 1.7.0_72
-
-
-
- 1.1.9.v20141016
- 7.1.2.v20141202
-
-
-
- npn-alpn-7u75
-
-
- java.version
- 1.7.0_75
-
-
-
- 1.1.10.v20150130
- 7.1.3.v20150130
-
-
-
- npn-alpn-7u76
-
-
- java.version
- 1.7.0_76
-
-
-
- 1.1.10.v20150130
- 7.1.3.v20150130
-
-
-
- npn-alpn-7u79
-
-
- java.version
- 1.7.0_79
-
-
-
- 1.1.10.v20150130
- 7.1.3.v20150130
-
-
-
- npn-alpn-7u80
-
-
- java.version
- 1.7.0_80
-
-
-
- 1.1.11.v20150415
- 7.1.3.v20150130
-
-
-
- alpn-8u05
-
-
- java.version
- 1.8.0_05
-
-
-
- 8.1.0.v20141016
-
-
-
- alpn-8u11
-
-
- java.version
- 1.8.0_11
-
-
-
- 8.1.0.v20141016
-
-
-
- alpn-8u20
-
-
- java.version
- 1.8.0_20
-
-
-
- 8.1.0.v20141016
-
-
-
- alpn-8u25
-
-
- java.version
- 1.8.0_25
-
-
-
- 8.1.2.v20141202
-
-
-
- alpn-8u31
-
-
- java.version
- 1.8.0_31
-
-
-
- 8.1.3.v20150130
-
-
-
- alpn-8u40
-
-
- java.version
- 1.8.0_40
-
-
-
- 8.1.3.v20150130
-
-
-
- alpn-8u45
-
-
- java.version
- 1.8.0_45
-
-
-
- 8.1.3.v20150130
-
-
-
- alpn-8u51
-
-
- java.version
- 1.8.0_51
-
-
-
- 8.1.4.v20150727
-
-
- -Xbootclasspath/p:${jetty.alpn.path}
+
+ -javaagent:${jetty.alpnAgent.path}=${jetty.alpnAgent.option}-D_-D_
@@ -659,21 +264,13 @@
org.eclipse.jetty.npnnpn-api1.1.1.v20141010
-
-
- org.mortbay.jetty.npn
- npn-boot
- ${jetty.npn.version}
+ providedorg.eclipse.jetty.alpnalpn-api1.1.2.v20150522
-
-
- org.mortbay.jetty.alpn
- alpn-boot
- ${jetty.alpn.version}
+ provided
@@ -687,7 +284,7 @@
${project.groupId}netty-tcnative
- 1.1.33.Fork10
+ 1.1.33.Fork11${tcnative.classifier}compiletrue
@@ -1057,27 +654,15 @@
maven-dependency-plugin
- get-npn-boot
- validate
-
- get
-
-
- org.mortbay.jetty.npn
- npn-boot
- ${jetty.npn.version}
-
-
-
- get-alpn-boot
+ get-jetty-alpn-agentvalidateget
- org.mortbay.jetty.alpn
- alpn-boot
- ${jetty.alpn.version}
+ kr.motd.javaagent
+ jetty-alpn-agent
+ ${jetty.alpnAgent.version}
@@ -1094,7 +679,7 @@
**/TestUtil*random
- ${argLine.common} ${argLine.bootcp} ${argLine.leak} ${argLine.coverage}
+ ${argLine.common} ${argLine.alpnAgent} ${argLine.leak} ${argLine.coverage}
@@ -1150,11 +735,11 @@
2
- ${name}
- ${groupId}.${artifactId}.source
- ${organization.name}
+ ${project.name}
+ ${project.groupId}.${project.artifactId}.source
+ ${project.organization.name}${parsedVersion.osgiVersion}
- ${groupId}.${artifactId};version="${parsedVersion.osgiVersion}";roots:="."
+ ${project.groupId}.${project.artifactId};version="${parsedVersion.osgiVersion}";roots:="."
diff -Nru netty-4.0.33/tarball/pom.xml netty-4.0.34/tarball/pom.xml
--- netty-4.0.33/tarball/pom.xml 2015-11-03 13:18:17.000000000 +0000
+++ netty-4.0.34/tarball/pom.xml 2016-01-29 08:23:46.000000000 +0000
@@ -20,7 +20,7 @@
io.nettynetty-parent
- 4.0.33.Final
+ 4.0.34.Finalnetty-tarball
diff -Nru netty-4.0.33/testsuite/pom.xml netty-4.0.34/testsuite/pom.xml
--- netty-4.0.33/testsuite/pom.xml 2015-11-03 13:18:17.000000000 +0000
+++ netty-4.0.34/testsuite/pom.xml 2016-01-29 08:23:46.000000000 +0000
@@ -20,7 +20,7 @@
io.nettynetty-parent
- 4.0.33.Final
+ 4.0.34.Finalnetty-testsuite
diff -Nru netty-4.0.33/testsuite-osgi/pom.xml netty-4.0.34/testsuite-osgi/pom.xml
--- netty-4.0.33/testsuite-osgi/pom.xml 2015-11-03 13:18:17.000000000 +0000
+++ netty-4.0.34/testsuite-osgi/pom.xml 2016-01-29 08:23:46.000000000 +0000
@@ -20,7 +20,7 @@
io.nettynetty-parent
- 4.0.33.Final
+ 4.0.34.Finalnetty-testsuite-osgi
diff -Nru netty-4.0.33/transport/pom.xml netty-4.0.34/transport/pom.xml
--- netty-4.0.33/transport/pom.xml 2015-11-03 13:18:17.000000000 +0000
+++ netty-4.0.34/transport/pom.xml 2016-01-29 08:23:46.000000000 +0000
@@ -20,7 +20,7 @@
io.nettynetty-parent
- 4.0.33.Final
+ 4.0.34.Finalnetty-transport
diff -Nru netty-4.0.33/transport/src/main/java/io/netty/bootstrap/AbstractBootstrap.java netty-4.0.34/transport/src/main/java/io/netty/bootstrap/AbstractBootstrap.java
--- netty-4.0.33/transport/src/main/java/io/netty/bootstrap/AbstractBootstrap.java 2015-11-03 13:18:17.000000000 +0000
+++ netty-4.0.34/transport/src/main/java/io/netty/bootstrap/AbstractBootstrap.java 2016-01-29 08:23:46.000000000 +0000
@@ -29,6 +29,7 @@
import io.netty.util.AttributeKey;
import io.netty.util.concurrent.EventExecutor;
import io.netty.util.concurrent.GlobalEventExecutor;
+import io.netty.util.internal.OneTimeTask;
import io.netty.util.internal.StringUtil;
import java.net.InetAddress;
@@ -341,7 +342,7 @@
// This method is invoked before channelRegistered() is triggered. Give user handlers a chance to set up
// the pipeline in its channelRegistered() implementation.
- channel.eventLoop().execute(new Runnable() {
+ channel.eventLoop().execute(new OneTimeTask() {
@Override
public void run() {
if (regFuture.isSuccess()) {
diff -Nru netty-4.0.33/transport/src/main/java/io/netty/bootstrap/Bootstrap.java netty-4.0.34/transport/src/main/java/io/netty/bootstrap/Bootstrap.java
--- netty-4.0.33/transport/src/main/java/io/netty/bootstrap/Bootstrap.java 2015-11-03 13:18:17.000000000 +0000
+++ netty-4.0.34/transport/src/main/java/io/netty/bootstrap/Bootstrap.java 2016-01-29 08:23:46.000000000 +0000
@@ -23,6 +23,7 @@
import io.netty.channel.ChannelPromise;
import io.netty.channel.EventLoopGroup;
import io.netty.util.AttributeKey;
+import io.netty.util.internal.OneTimeTask;
import io.netty.util.internal.logging.InternalLogger;
import io.netty.util.internal.logging.InternalLoggerFactory;
@@ -158,7 +159,7 @@
// This method is invoked before channelRegistered() is triggered. Give user handlers a chance to set up
// the pipeline in its channelRegistered() implementation.
- channel.eventLoop().execute(new Runnable() {
+ channel.eventLoop().execute(new OneTimeTask() {
@Override
public void run() {
if (regFuture.isSuccess()) {
diff -Nru netty-4.0.33/transport/src/main/java/io/netty/bootstrap/ServerBootstrap.java netty-4.0.34/transport/src/main/java/io/netty/bootstrap/ServerBootstrap.java
--- netty-4.0.33/transport/src/main/java/io/netty/bootstrap/ServerBootstrap.java 2015-11-03 13:18:17.000000000 +0000
+++ netty-4.0.34/transport/src/main/java/io/netty/bootstrap/ServerBootstrap.java 2016-01-29 08:23:46.000000000 +0000
@@ -28,6 +28,7 @@
import io.netty.channel.EventLoopGroup;
import io.netty.channel.ServerChannel;
import io.netty.util.AttributeKey;
+import io.netty.util.internal.OneTimeTask;
import io.netty.util.internal.StringUtil;
import io.netty.util.internal.logging.InternalLogger;
import io.netty.util.internal.logging.InternalLoggerFactory;
@@ -274,7 +275,7 @@
// stop accept new connections for 1 second to allow the channel to recover
// See https://github.com/netty/netty/issues/1328
config.setAutoRead(false);
- ctx.channel().eventLoop().schedule(new Runnable() {
+ ctx.channel().eventLoop().schedule(new OneTimeTask() {
@Override
public void run() {
config.setAutoRead(true);
diff -Nru netty-4.0.33/transport/src/main/java/io/netty/channel/AbstractChannelHandlerContext.java netty-4.0.34/transport/src/main/java/io/netty/channel/AbstractChannelHandlerContext.java
--- netty-4.0.33/transport/src/main/java/io/netty/channel/AbstractChannelHandlerContext.java 2015-11-03 13:18:17.000000000 +0000
+++ netty-4.0.34/transport/src/main/java/io/netty/channel/AbstractChannelHandlerContext.java 2016-01-29 08:23:46.000000000 +0000
@@ -15,27 +15,17 @@
*/
package io.netty.channel;
-import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;
-import io.netty.buffer.ByteBufHolder;
import io.netty.util.DefaultAttributeMap;
import io.netty.util.Recycler;
import io.netty.util.ReferenceCountUtil;
import io.netty.util.concurrent.EventExecutor;
-import io.netty.util.concurrent.EventExecutorGroup;
-import io.netty.util.concurrent.FastThreadLocal;
import io.netty.util.internal.OneTimeTask;
import io.netty.util.internal.RecyclableMpscLinkedQueueNode;
import io.netty.util.internal.StringUtil;
+import io.netty.util.internal.SystemPropertyUtil;
-import java.lang.reflect.Field;
-import java.lang.reflect.Modifier;
import java.net.SocketAddress;
-import java.nio.ByteBuffer;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-import java.util.WeakHashMap;
import static io.netty.channel.DefaultChannelPipeline.*;
@@ -46,10 +36,24 @@
private final boolean inbound;
private final boolean outbound;
- private final AbstractChannel channel;
private final DefaultChannelPipeline pipeline;
private final String name;
- private boolean removed;
+ private boolean handlerRemoved;
+
+ /**
+ * This is set to {@code true} once the {@link ChannelHandler#handlerAdded(ChannelHandlerContext) method is called.
+ * We need to keep track of this to ensure we will never call another {@link ChannelHandler} method before
+ * handlerAdded(...) is called to guard against ordering issues.
+ * {@link ChannelHandler#handlerAdded(ChannelHandlerContext)} MUST be the first
+ * method that is called for handler when it becomes a part of the {@link ChannelPipeline} in all cases. Not doing
+ * so may lead to unexpected side-effects as {@link ChannelHandler} implementations may need to do initialization
+ * steps before a {@link ChannelHandler} can be used.
+ *
+ * See #4705
+ *
+ * No need to mark volatile as this will be made visible as next/prev is volatile.
+ */
+ private boolean handlerAdded;
// Will be set to null if no child executor should be used, otherwise it will be set to the
// child executor.
@@ -64,37 +68,23 @@
private volatile Runnable invokeChannelWritableStateChangedTask;
private volatile Runnable invokeFlushTask;
- AbstractChannelHandlerContext(DefaultChannelPipeline pipeline, EventExecutorGroup group, String name,
+ AbstractChannelHandlerContext(DefaultChannelPipeline pipeline, EventExecutor executor, String name,
boolean inbound, boolean outbound) {
if (name == null) {
throw new NullPointerException("name");
}
- channel = pipeline.channel;
this.pipeline = pipeline;
this.name = name;
-
- if (group != null) {
- // Pin one of the child executors once and remember it so that the same child executor
- // is used to fire events for the same channel.
- EventExecutor childExecutor = pipeline.childExecutors.get(group);
- if (childExecutor == null) {
- childExecutor = group.next();
- pipeline.childExecutors.put(group, childExecutor);
- }
- executor = childExecutor;
- } else {
- executor = null;
- }
-
+ this.executor = executor;
this.inbound = inbound;
this.outbound = outbound;
}
@Override
public Channel channel() {
- return channel;
+ return pipeline.channel();
}
@Override
@@ -125,7 +115,7 @@
public ChannelHandlerContext fireChannelRegistered() {
final AbstractChannelHandlerContext next = findContextInbound();
EventExecutor executor = next.executor();
- if (executor.inEventLoop()) {
+ if (next.isHandlerAddedCalled() && executor.inEventLoop()) {
next.invokeChannelRegistered();
} else {
executor.execute(new OneTimeTask() {
@@ -150,7 +140,7 @@
public ChannelHandlerContext fireChannelUnregistered() {
final AbstractChannelHandlerContext next = findContextInbound();
EventExecutor executor = next.executor();
- if (executor.inEventLoop()) {
+ if (next.isHandlerAddedCalled() && executor.inEventLoop()) {
next.invokeChannelUnregistered();
} else {
executor.execute(new OneTimeTask() {
@@ -175,7 +165,7 @@
public ChannelHandlerContext fireChannelActive() {
final AbstractChannelHandlerContext next = findContextInbound();
EventExecutor executor = next.executor();
- if (executor.inEventLoop()) {
+ if (next.isHandlerAddedCalled() && executor.inEventLoop()) {
next.invokeChannelActive();
} else {
executor.execute(new OneTimeTask() {
@@ -200,7 +190,7 @@
public ChannelHandlerContext fireChannelInactive() {
final AbstractChannelHandlerContext next = findContextInbound();
EventExecutor executor = next.executor();
- if (executor.inEventLoop()) {
+ if (next.isHandlerAddedCalled() && executor.inEventLoop()) {
next.invokeChannelInactive();
} else {
executor.execute(new OneTimeTask() {
@@ -230,7 +220,7 @@
final AbstractChannelHandlerContext next = this.next;
EventExecutor executor = next.executor();
- if (executor.inEventLoop()) {
+ if (next.isHandlerAddedCalled() && executor.inEventLoop()) {
next.invokeExceptionCaught(cause);
} else {
try {
@@ -247,7 +237,6 @@
}
}
}
-
return this;
}
@@ -271,7 +260,7 @@
final AbstractChannelHandlerContext next = findContextInbound();
EventExecutor executor = next.executor();
- if (executor.inEventLoop()) {
+ if (next.isHandlerAddedCalled() && executor.inEventLoop()) {
next.invokeUserEventTriggered(event);
} else {
executor.execute(new OneTimeTask() {
@@ -300,7 +289,7 @@
final AbstractChannelHandlerContext next = findContextInbound();
EventExecutor executor = next.executor();
- if (executor.inEventLoop()) {
+ if (next.isHandlerAddedCalled() && executor.inEventLoop()) {
next.invokeChannelRead(msg);
} else {
executor.execute(new OneTimeTask() {
@@ -325,7 +314,7 @@
public ChannelHandlerContext fireChannelReadComplete() {
final AbstractChannelHandlerContext next = findContextInbound();
EventExecutor executor = next.executor();
- if (executor.inEventLoop()) {
+ if (next.isHandlerAddedCalled() && executor.inEventLoop()) {
next.invokeChannelReadComplete();
} else {
Runnable task = next.invokeChannelReadCompleteTask;
@@ -354,7 +343,7 @@
public ChannelHandlerContext fireChannelWritabilityChanged() {
final AbstractChannelHandlerContext next = findContextInbound();
EventExecutor executor = next.executor();
- if (executor.inEventLoop()) {
+ if (next.isHandlerAddedCalled() && executor.inEventLoop()) {
next.invokeChannelWritabilityChanged();
} else {
Runnable task = next.invokeChannelWritableStateChangedTask;
@@ -421,7 +410,7 @@
final AbstractChannelHandlerContext next = findContextOutbound();
EventExecutor executor = next.executor();
- if (executor.inEventLoop()) {
+ if (next.isHandlerAddedCalled() && executor.inEventLoop()) {
next.invokeBind(localAddress, promise);
} else {
safeExecute(executor, new OneTimeTask() {
@@ -431,7 +420,6 @@
}
}, promise, null);
}
-
return promise;
}
@@ -462,7 +450,7 @@
final AbstractChannelHandlerContext next = findContextOutbound();
EventExecutor executor = next.executor();
- if (executor.inEventLoop()) {
+ if (next.isHandlerAddedCalled() && executor.inEventLoop()) {
next.invokeConnect(remoteAddress, localAddress, promise);
} else {
safeExecute(executor, new OneTimeTask() {
@@ -472,7 +460,6 @@
}
}, promise, null);
}
-
return promise;
}
@@ -493,7 +480,7 @@
final AbstractChannelHandlerContext next = findContextOutbound();
EventExecutor executor = next.executor();
- if (executor.inEventLoop()) {
+ if (next.isHandlerAddedCalled() && executor.inEventLoop()) {
// Translate disconnect to close if the channel has no notion of disconnect-reconnect.
// So far, UDP/IP is the only transport that has such behavior.
if (!channel().metadata().hasDisconnect()) {
@@ -513,7 +500,6 @@
}
}, promise, null);
}
-
return promise;
}
@@ -534,7 +520,7 @@
final AbstractChannelHandlerContext next = findContextOutbound();
EventExecutor executor = next.executor();
- if (executor.inEventLoop()) {
+ if (next.isHandlerAddedCalled() && executor.inEventLoop()) {
next.invokeClose(promise);
} else {
safeExecute(executor, new OneTimeTask() {
@@ -565,7 +551,7 @@
final AbstractChannelHandlerContext next = findContextOutbound();
EventExecutor executor = next.executor();
- if (executor.inEventLoop()) {
+ if (next.isHandlerAddedCalled() && executor.inEventLoop()) {
next.invokeDeregister(promise);
} else {
safeExecute(executor, new OneTimeTask() {
@@ -591,7 +577,7 @@
public ChannelHandlerContext read() {
final AbstractChannelHandlerContext next = findContextOutbound();
EventExecutor executor = next.executor();
- if (executor.inEventLoop()) {
+ if (next.isHandlerAddedCalled() && executor.inEventLoop()) {
next.invokeRead();
} else {
Runnable task = next.invokeReadTask;
@@ -650,7 +636,7 @@
public ChannelHandlerContext flush() {
final AbstractChannelHandlerContext next = findContextOutbound();
EventExecutor executor = next.executor();
- if (executor.inEventLoop()) {
+ if (next.isHandlerAddedCalled() && executor.inEventLoop()) {
next.invokeFlush();
} else {
Runnable task = next.invokeFlushTask;
@@ -662,7 +648,7 @@
}
};
}
- safeExecute(executor, task, channel.voidPromise(), null);
+ safeExecute(executor, task, channel().voidPromise(), null);
}
return this;
@@ -696,7 +682,7 @@
private void write(Object msg, boolean flush, ChannelPromise promise) {
AbstractChannelHandlerContext next = findContextOutbound();
EventExecutor executor = next.executor();
- if (executor.inEventLoop()) {
+ if (next.isHandlerAddedCalled() && executor.inEventLoop()) {
next.invokeWrite(msg, promise);
if (flush) {
next.invokeFlush();
@@ -837,16 +823,24 @@
@Override
public ChannelPromise voidPromise() {
- return channel.voidPromise();
+ return channel().voidPromise();
}
void setRemoved() {
- removed = true;
+ handlerRemoved = true;
}
@Override
public boolean isRemoved() {
- return removed;
+ return handlerRemoved;
+ }
+
+ final void setHandlerAddedCalled() {
+ handlerAdded = true;
+ }
+
+ final boolean isHandlerAddedCalled() {
+ return handlerAdded;
}
private static void safeExecute(EventExecutor executor, Runnable runnable, ChannelPromise promise, Object msg) {
@@ -865,23 +859,12 @@
abstract static class AbstractWriteTask extends RecyclableMpscLinkedQueueNode implements Runnable {
- private static final FastThreadLocal