diff --git a/all/pom.xml b/all/pom.xml index 9df6cdb3da..7f4fce2356 100644 --- a/all/pom.xml +++ b/all/pom.xml @@ -20,7 +20,7 @@ io.netty netty-parent - 4.0.0.Final-SNAPSHOT + 4.0.0.CR4-SNAPSHOT netty-all diff --git a/buffer/pom.xml b/buffer/pom.xml index 310ebb5649..93e1e56f39 100644 --- a/buffer/pom.xml +++ b/buffer/pom.xml @@ -20,7 +20,7 @@ io.netty netty-parent - 4.0.0.Final-SNAPSHOT + 4.0.0.CR4-SNAPSHOT netty-buffer diff --git a/buffer/src/main/java/io/netty/buffer/AbstractByteBuf.java b/buffer/src/main/java/io/netty/buffer/AbstractByteBuf.java index 0828ab1e0b..21351f8a13 100644 --- a/buffer/src/main/java/io/netty/buffer/AbstractByteBuf.java +++ b/buffer/src/main/java/io/netty/buffer/AbstractByteBuf.java @@ -50,11 +50,6 @@ public abstract class AbstractByteBuf implements ByteBuf { this.maxCapacity = maxCapacity; } - @Override - public BufType type() { - return BufType.BYTE; - } - @Override public int maxCapacity() { return maxCapacity; @@ -971,17 +966,17 @@ public abstract class AbstractByteBuf implements ByteBuf { nioBuffer.flip(); } - return BufUtil.decodeString(nioBuffer, charset); + return ByteBufUtil.decodeString(nioBuffer, charset); } @Override public int indexOf(int fromIndex, int toIndex, byte value) { - return BufUtil.indexOf(this, fromIndex, toIndex, value); + return ByteBufUtil.indexOf(this, fromIndex, toIndex, value); } @Override public int indexOf(int fromIndex, int toIndex, ByteBufIndexFinder indexFinder) { - return BufUtil.indexOf(this, fromIndex, toIndex, indexFinder); + return ByteBufUtil.indexOf(this, fromIndex, toIndex, indexFinder); } @Override @@ -1027,7 +1022,7 @@ public abstract class AbstractByteBuf implements ByteBuf { @Override public int hashCode() { - return BufUtil.hashCode(this); + return ByteBufUtil.hashCode(this); } @Override @@ -1036,14 +1031,14 @@ public abstract class AbstractByteBuf implements ByteBuf { return true; } if (o instanceof ByteBuf) { - return BufUtil.equals(this, (ByteBuf) o); + return ByteBufUtil.equals(this, (ByteBuf) o); } return false; } @Override public int compareTo(ByteBuf that) { - return BufUtil.compare(this, that); + return ByteBufUtil.compare(this, that); } @Override diff --git a/buffer/src/main/java/io/netty/buffer/AbstractDerivedByteBuf.java b/buffer/src/main/java/io/netty/buffer/AbstractDerivedByteBuf.java index 4ef5961f55..13f906f6a6 100644 --- a/buffer/src/main/java/io/netty/buffer/AbstractDerivedByteBuf.java +++ b/buffer/src/main/java/io/netty/buffer/AbstractDerivedByteBuf.java @@ -52,14 +52,4 @@ public abstract class AbstractDerivedByteBuf extends AbstractByteBuf { public final boolean release(int decrement) { return unwrap().release(decrement); } - - @Override - public final ByteBuf suspendIntermediaryDeallocations() { - throw new UnsupportedOperationException("derived"); - } - - @Override - public final ByteBuf resumeIntermediaryDeallocations() { - throw new UnsupportedOperationException("derived"); - } } diff --git a/buffer/src/main/java/io/netty/buffer/AbstractMessageBuf.java b/buffer/src/main/java/io/netty/buffer/AbstractMessageBuf.java deleted file mode 100644 index ec9067239c..0000000000 --- a/buffer/src/main/java/io/netty/buffer/AbstractMessageBuf.java +++ /dev/null @@ -1,258 +0,0 @@ -/* - * Copyright 2013 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.internal.PlatformDependent; - -import java.util.AbstractQueue; -import java.util.Collection; -import java.util.concurrent.atomic.AtomicIntegerFieldUpdater; - -/** - * Abstract base class for {@link MessageBuf} implementations. - * @param - */ -public abstract class AbstractMessageBuf extends AbstractQueue implements MessageBuf { - - @SuppressWarnings("rawtypes") - private static final AtomicIntegerFieldUpdater refCntUpdater = - AtomicIntegerFieldUpdater.newUpdater(AbstractMessageBuf.class, "refCnt"); - - private static final long REFCNT_FIELD_OFFSET; - - static { - long refCntFieldOffset = -1; - try { - if (PlatformDependent.hasUnsafe()) { - refCntFieldOffset = PlatformDependent.objectFieldOffset( - AbstractMessageBuf.class.getDeclaredField("refCnt")); - } - } catch (Throwable t) { - // Ignored - } - - REFCNT_FIELD_OFFSET = refCntFieldOffset; - } - - private final int maxCapacity; - - @SuppressWarnings("FieldMayBeFinal") - private volatile int refCnt = 1; - - protected AbstractMessageBuf(int maxCapacity) { - if (maxCapacity < 0) { - throw new IllegalArgumentException("maxCapacity: " + maxCapacity + " (expected: >= 0)"); - } - this.maxCapacity = maxCapacity; - } - - @Override - public final BufType type() { - return BufType.MESSAGE; - } - - @Override - public final int refCnt() { - if (REFCNT_FIELD_OFFSET >= 0) { - // Try to do non-volatile read for performance. - return PlatformDependent.getInt(this, REFCNT_FIELD_OFFSET); - } else { - return refCnt; - } - } - - @Override - public MessageBuf retain() { - for (;;) { - int refCnt = this.refCnt; - if (refCnt == 0) { - throw new IllegalBufferAccessException(); - } - if (refCnt == Integer.MAX_VALUE) { - throw new IllegalBufferAccessException("refCnt overflow"); - } - if (refCntUpdater.compareAndSet(this, refCnt, refCnt + 1)) { - break; - } - } - return this; - } - - @Override - public MessageBuf retain(int increment) { - if (increment <= 0) { - throw new IllegalArgumentException("increment: " + increment + " (expected: > 0)"); - } - - for (;;) { - int refCnt = this.refCnt; - if (refCnt == 0) { - throw new IllegalBufferAccessException(); - } - if (refCnt > Integer.MAX_VALUE - increment) { - throw new IllegalBufferAccessException("refCnt overflow"); - } - if (refCntUpdater.compareAndSet(this, refCnt, refCnt + increment)) { - break; - } - } - return this; - } - - @Override - public final boolean release() { - for (;;) { - int refCnt = this.refCnt; - if (refCnt == 0) { - throw new IllegalBufferAccessException(); - } - - if (refCntUpdater.compareAndSet(this, refCnt, refCnt - 1)) { - if (refCnt == 1) { - deallocate(); - return true; - } - return false; - } - } - } - - @Override - public final boolean release(int decrement) { - if (decrement <= 0) { - throw new IllegalArgumentException("decrement: " + decrement + " (expected: > 0)"); - } - - for (;;) { - int refCnt = this.refCnt; - if (refCnt < decrement) { - throw new IllegalBufferAccessException(); - } - - if (refCntUpdater.compareAndSet(this, refCnt, refCnt - decrement)) { - if (refCnt == decrement) { - deallocate(); - return true; - } - return false; - } - } - } - - protected abstract void deallocate(); - - @Override - public final int maxCapacity() { - return maxCapacity; - } - - @Override - public final boolean isReadable() { - return !isEmpty(); - } - - @Override - public final boolean isReadable(int size) { - if (size < 0) { - throw new IllegalArgumentException("size: " + size + " (expected: >= 0)"); - } - return size() >= size; - } - - @Override - public final boolean isWritable() { - return size() < maxCapacity; - } - - @Override - public final boolean isWritable(int size) { - if (size < 0) { - throw new IllegalArgumentException("size: " + size + " (expected: >= 0)"); - } - return size() <= maxCapacity - size; - } - - protected final void ensureAccessible() { - if (refCnt <= 0) { - throw new IllegalBufferAccessException(); - } - } - - @Override - public final boolean add(T t) { - return super.add(t); - } - - @Override - public final T remove() { - return super.remove(); - } - - @Override - public final T element() { - return super.element(); - } - - @Override - public int drainTo(Collection super T> c) { - ensureAccessible(); - int cnt = 0; - for (;;) { - T o = poll(); - if (o == null) { - break; - } - c.add(o); - cnt ++; - } - return cnt; - } - - @Override - public int drainTo(Collection super T> c, int maxElements) { - ensureAccessible(); - int cnt = 0; - while (cnt < maxElements) { - T o = poll(); - if (o == null) { - break; - } - c.add(o); - cnt ++; - } - return cnt; - } - - @Override - public String toString() { - if (refCnt <= 0) { - return getClass().getSimpleName() + "(freed)"; - } - - StringBuilder buf = new StringBuilder(); - buf.append(getClass().getSimpleName()); - buf.append("(size: "); - buf.append(size()); - if (maxCapacity != Integer.MAX_VALUE) { - buf.append('/'); - buf.append(maxCapacity); - } - buf.append(')'); - - return buf.toString(); - } -} diff --git a/buffer/src/main/java/io/netty/buffer/Buf.java b/buffer/src/main/java/io/netty/buffer/Buf.java deleted file mode 100644 index 5cf36606e7..0000000000 --- a/buffer/src/main/java/io/netty/buffer/Buf.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright 2012 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; - -/** - * A buffer to operate on - */ -public interface Buf extends ReferenceCounted { - /** - * The BufType which will be handled by the Buf implementation - */ - BufType type(); - - /** - * Returns the maximum allowed capacity of this buffer. - */ - int maxCapacity(); - - /** - * Returns {@code true} if and only if this buffer contains at least one readable element. - */ - boolean isReadable(); - - /** - * Returns {@code true} if and only if this buffer contains equal to or more than the specified number of elements. - */ - boolean isReadable(int size); - - /** - * Returns {@code true} if and only if this buffer has enough room to allow writing one element. - */ - boolean isWritable(); - - /** - * Returns {@code true} if and only if this buffer has enough room to allow writing the specified number of - * elements. - */ - boolean isWritable(int size); - - @Override - Buf retain(); - - @Override - Buf retain(int increment); -} diff --git a/buffer/src/main/java/io/netty/buffer/ByteBuf.java b/buffer/src/main/java/io/netty/buffer/ByteBuf.java index ce0c68ea71..b201d26328 100644 --- a/buffer/src/main/java/io/netty/buffer/ByteBuf.java +++ b/buffer/src/main/java/io/netty/buffer/ByteBuf.java @@ -227,7 +227,7 @@ import java.nio.charset.UnsupportedCharsetException; * Please refer to {@link ByteBufInputStream} and * {@link ByteBufOutputStream}. */ -public interface ByteBuf extends Buf, Comparable { +public interface ByteBuf extends ReferenceCounted, Comparable { /** * Returns the number of bytes (octets) this buffer can contain. @@ -248,7 +248,6 @@ public interface ByteBuf extends Buf, Comparable { * {@link #ensureWritable(int)}, those methods will raise an * {@link IllegalArgumentException}. */ - @Override int maxCapacity(); /** @@ -391,9 +390,13 @@ public interface ByteBuf extends Buf, Comparable { * if and only if {@code (this.writerIndex - this.readerIndex)} is greater * than {@code 0}. */ - @Override boolean isReadable(); + /** + * Returns {@code true} if and only if this buffer contains equal to or more than the specified number of elements. + */ + boolean isReadable(int size); + /** * @deprecated Use {@link #isReadable()} or {@link #isReadable(int)} instead. */ @@ -405,9 +408,14 @@ public interface ByteBuf extends Buf, Comparable { * if and only if {@code (this.capacity - this.writerIndex)} is greater * than {@code 0}. */ - @Override boolean isWritable(); + /** + * Returns {@code true} if and only if this buffer has enough room to allow writing the specified number of + * elements. + */ + boolean isWritable(int size); + /** * @deprecated Use {@link #isWritable()} or {@link #isWritable(int)} instead. */ @@ -1869,23 +1877,6 @@ public interface ByteBuf extends Buf, Comparable { */ String toString(int index, int length, Charset charset); - /** - * Suspends the intermediary deallocation of the internal memory block of this buffer until asked via - * {@link #resumeIntermediaryDeallocations()}. An intermediary deallocation is usually made when the capacity of - * a buffer changes. - * - * @throws UnsupportedOperationException if this buffer is derived - */ - ByteBuf suspendIntermediaryDeallocations(); - - /** - * Resumes the intermediary deallocation of the internal memory block of this buffer, suspended by - * {@link #suspendIntermediaryDeallocations()}. - * - * @throws UnsupportedOperationException if this buffer is derived - */ - ByteBuf resumeIntermediaryDeallocations(); - /** * Returns a hash code which was calculated from the content of this * buffer. If there's a byte array which is diff --git a/buffer/src/main/java/io/netty/buffer/BufUtil.java b/buffer/src/main/java/io/netty/buffer/ByteBufUtil.java similarity index 94% rename from buffer/src/main/java/io/netty/buffer/BufUtil.java rename to buffer/src/main/java/io/netty/buffer/ByteBufUtil.java index b651316387..323b26ed25 100644 --- a/buffer/src/main/java/io/netty/buffer/BufUtil.java +++ b/buffer/src/main/java/io/netty/buffer/ByteBufUtil.java @@ -25,13 +25,11 @@ import java.nio.charset.Charset; import java.nio.charset.CharsetDecoder; import java.nio.charset.CharsetEncoder; import java.nio.charset.CoderResult; -import java.util.Iterator; /** - * A collection of utility methods that is related with handling {@link ByteBuf}, {@link MessageBuf}, and their - * elements. + * A collection of utility methods that is related with handling {@link ByteBuf}. */ -public final class BufUtil { +public final class ByteBufUtil { private static final char[] HEXDUMP_TABLE = new char[256 * 4]; @@ -418,29 +416,5 @@ public final class BufUtil { return dst.flip().toString(); } - /** - * Return the content of the given {@link MessageBuf} as string representation. - */ - public static String contentToString(MessageBuf> buf) { - if (buf.isEmpty()) { - return "[]"; - } - Iterator> it = buf.iterator(); - StringBuilder sb = new StringBuilder(); - sb.append('['); - while (it.hasNext()) { - Object msg = it.next(); - if (msg == buf) { - sb.append('(' + buf.getClass().getSimpleName() + ')'); - } else { - sb.append(msg); - } - if (it.hasNext()) { - sb.append(", "); - } - } - return sb.append(']').toString(); - } - - private BufUtil() { } + private ByteBufUtil() { } } diff --git a/buffer/src/main/java/io/netty/buffer/CompositeByteBuf.java b/buffer/src/main/java/io/netty/buffer/CompositeByteBuf.java index 483390bd33..f39a50608f 100644 --- a/buffer/src/main/java/io/netty/buffer/CompositeByteBuf.java +++ b/buffer/src/main/java/io/netty/buffer/CompositeByteBuf.java @@ -387,12 +387,6 @@ public interface CompositeByteBuf extends ByteBuf, Iterable { @Override CompositeByteBuf writeZero(int length); - @Override - CompositeByteBuf suspendIntermediaryDeallocations(); - - @Override - CompositeByteBuf resumeIntermediaryDeallocations(); - @Override CompositeByteBuf retain(int increment); diff --git a/buffer/src/main/java/io/netty/buffer/DefaultCompositeByteBuf.java b/buffer/src/main/java/io/netty/buffer/DefaultCompositeByteBuf.java index 49dc661d29..9dfd3ddf0e 100644 --- a/buffer/src/main/java/io/netty/buffer/DefaultCompositeByteBuf.java +++ b/buffer/src/main/java/io/netty/buffer/DefaultCompositeByteBuf.java @@ -26,14 +26,12 @@ import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.channels.GatheringByteChannel; import java.nio.channels.ScatteringByteChannel; -import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.ListIterator; -import java.util.Queue; /** @@ -50,7 +48,6 @@ public class DefaultCompositeByteBuf extends AbstractReferenceCountedByteBuf imp private final int maxNumComponents; private boolean freed; - private Queue suspendedDeallocations; public DefaultCompositeByteBuf(ByteBufAllocator alloc, boolean direct, int maxNumComponents) { super(Integer.MAX_VALUE); @@ -1202,11 +1199,7 @@ public class DefaultCompositeByteBuf extends AbstractReferenceCountedByteBuf imp void freeIfNecessary() { // Unwrap so that we can free slices, too. - if (suspendedDeallocations == null) { - buf.release(); // We should not get a NPE here. If so, it must be a bug. - } else { - suspendedDeallocations.add(buf); - } + buf.release(); // We should not get a NPE here. If so, it must be a bug. } } @@ -1457,7 +1450,6 @@ public class DefaultCompositeByteBuf extends AbstractReferenceCountedByteBuf imp } freed = true; - resumeIntermediaryDeallocations(); for (Component c: components) { c.freeIfNecessary(); } @@ -1465,30 +1457,6 @@ public class DefaultCompositeByteBuf extends AbstractReferenceCountedByteBuf imp leak.close(); } - @Override - public CompositeByteBuf suspendIntermediaryDeallocations() { - ensureAccessible(); - if (suspendedDeallocations == null) { - suspendedDeallocations = new ArrayDeque(2); - } - return this; - } - - @Override - public CompositeByteBuf resumeIntermediaryDeallocations() { - if (suspendedDeallocations == null) { - return this; - } - - Queue suspendedDeallocations = this.suspendedDeallocations; - this.suspendedDeallocations = null; - - for (ByteBuf buf: suspendedDeallocations) { - buf.release(); - } - return this; - } - @Override public ByteBuf unwrap() { return null; diff --git a/buffer/src/main/java/io/netty/buffer/DefaultMessageBuf.java b/buffer/src/main/java/io/netty/buffer/DefaultMessageBuf.java deleted file mode 100644 index 300b3d46b1..0000000000 --- a/buffer/src/main/java/io/netty/buffer/DefaultMessageBuf.java +++ /dev/null @@ -1,337 +0,0 @@ -/* - * Copyright 2012 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. - */ -/* - * Written by Josh Bloch of Google Inc. and released to the public domain, - * as explained at http://creativecommons.org/publicdomain/zero/1.0/. - */ -package io.netty.buffer; - -import java.lang.reflect.Array; -import java.util.ConcurrentModificationException; -import java.util.Iterator; -import java.util.NoSuchElementException; - -/** - * Default {@link MessageBuf} implementation. - * - * You should use {@link Unpooled#messageBuffer()} to create an instance - * - */ -public class DefaultMessageBuf extends AbstractMessageBuf { - - private static final int MIN_INITIAL_CAPACITY = 8; - private static final Object[] PLACEHOLDER = new Object[2]; - - private T[] elements; - private int head; - private int tail; - - protected DefaultMessageBuf() { - this(MIN_INITIAL_CAPACITY << 1); - } - - protected DefaultMessageBuf(int initialCapacity) { - this(initialCapacity, Integer.MAX_VALUE); - } - - protected DefaultMessageBuf(int initialCapacity, int maxCapacity) { - super(maxCapacity); - - if (initialCapacity < 0) { - throw new IllegalArgumentException("initialCapacity: " + initialCapacity + " (expected: >= 0)"); - } - if (maxCapacity < initialCapacity) { - throw new IllegalArgumentException( - "maxCapacity: " + maxCapacity + " (expected: >= initialCapacity(" + initialCapacity + ')'); - } - - // Find the best power of two to hold elements. - // Tests "<=" because arrays aren't kept full. - if (initialCapacity >= MIN_INITIAL_CAPACITY) { - initialCapacity |= initialCapacity >>> 1; - initialCapacity |= initialCapacity >>> 2; - initialCapacity |= initialCapacity >>> 4; - initialCapacity |= initialCapacity >>> 8; - initialCapacity |= initialCapacity >>> 16; - initialCapacity ++; - - if (initialCapacity < 0) { // Too many elements, must back off - initialCapacity >>>= 1; // Good luck allocating 2 ^ 30 elements - } - } else { - initialCapacity = MIN_INITIAL_CAPACITY; - } - - elements = cast(new Object[initialCapacity]); - } - - @Override - protected void deallocate() { - head = 0; - tail = 0; - elements = cast(PLACEHOLDER); - } - - @Override - public boolean offer(T e) { - if (e == null) { - throw new NullPointerException(); - } - - ensureAccessible(); - if (!isWritable()) { - return false; - } - - elements[tail] = e; - if ((tail = tail + 1 & elements.length - 1) == head) { - doubleCapacity(); - } - - return true; - } - - private void doubleCapacity() { - assert head == tail; - - int p = head; - int n = elements.length; - int r = n - p; // number of elements to the right of p - int newCapacity = n << 1; - if (newCapacity < 0) { - throw new IllegalStateException("Sorry, deque too big"); - } - Object[] a = new Object[newCapacity]; - System.arraycopy(elements, p, a, 0, r); - System.arraycopy(elements, 0, a, r, p); - elements = cast(a); - head = 0; - tail = n; - } - - @Override - public T poll() { - ensureAccessible(); - int h = head; - T result = elements[h]; // Element is null if deque empty - if (result == null) { - return null; - } - elements[h] = null; // Must null out slot - head = h + 1 & elements.length - 1; - return result; - } - - @Override - public T peek() { - ensureAccessible(); - return elements[head]; // elements[head] is null if deque empty - } - - @Override - public boolean remove(Object o) { - if (o == null) { - return false; - } - - ensureAccessible(); - int mask = elements.length - 1; - int i = head; - T x; - while ((x = elements[i]) != null) { - if (o.equals(x)) { - delete(i); - return true; - } - i = i + 1 & mask; - } - return false; - } - - private boolean delete(int i) { - assert elements[tail] == null; - assert head == tail ? elements[head] == null - : elements[head] != null && elements[tail - 1 & elements.length - 1] != null; - assert elements[head - 1 & elements.length - 1] == null; - - final T[] elements = this.elements; - final int mask = elements.length - 1; - final int h = head; - final int t = tail; - final int front = i - h & mask; - final int back = t - i & mask; - - // Invariant: head <= i < tail mod circularity - if (front >= (t - h & mask)) { - throw new ConcurrentModificationException(); - } - - // Optimize for least element motion - if (front < back) { - if (h <= i) { - System.arraycopy(elements, h, elements, h + 1, front); - } else { // Wrap around - System.arraycopy(elements, 0, elements, 1, i); - elements[0] = elements[mask]; - System.arraycopy(elements, h, elements, h + 1, mask - h); - } - elements[h] = null; - head = h + 1 & mask; - return false; - } else { - if (i < t) { // Copy the null tail as well - System.arraycopy(elements, i + 1, elements, i, back); - tail = t - 1; - } else { // Wrap around - System.arraycopy(elements, i + 1, elements, i, mask - i); - elements[mask] = elements[0]; - System.arraycopy(elements, 1, elements, 0, t); - tail = t - 1 & mask; - } - return true; - } - } - - @Override - public int size() { - return tail - head & elements.length - 1; - } - - @Override - public boolean isEmpty() { - return head == tail; - } - - @Override - public Iterator iterator() { - ensureAccessible(); - return new Itr(); - } - - @Override - public boolean contains(Object o) { - if (o == null) { - return false; - } - - ensureAccessible(); - final int mask = elements.length - 1; - int i = head; - Object e; - while ((e = elements[i]) != null) { - if (o.equals(e)) { - return true; - } - i = i + 1 & mask; - } - - return false; - } - - @Override - public void clear() { - ensureAccessible(); - int head = this.head; - int tail = this.tail; - if (head != tail) { - this.head = this.tail = 0; - final int mask = elements.length - 1; - int i = head; - do { - elements[i] = null; - i = i + 1 & mask; - } while (i != tail); - } - } - - @Override - public Object[] toArray() { - ensureAccessible(); - return copyElements(new Object[size()]); - } - - @Override - public T[] toArray(T[] a) { - ensureAccessible(); - int size = size(); - if (a.length < size) { - a = cast(Array.newInstance(a.getClass().getComponentType(), size)); - } - copyElements(a); - if (a.length > size) { - a[size] = null; - } - return a; - } - - private U[] copyElements(U[] a) { - if (head < tail) { - System.arraycopy(elements, head, cast(a), 0, size()); - } else if (head > tail) { - int headPortionLen = elements.length - head; - System.arraycopy(elements, head, cast(a), 0, headPortionLen); - System.arraycopy(elements, 0, cast(a), headPortionLen, tail); - } - return a; - } - - @SuppressWarnings({ "unchecked", "SuspiciousArrayCast" }) - private static T[] cast(Object a) { - return (T[]) a; - } - - private class Itr implements Iterator { - private int cursor = head; - private int fence = tail; - private int lastRet = -1; - - @Override - public boolean hasNext() { - ensureAccessible(); - return cursor != fence; - } - - @Override - public T next() { - ensureAccessible(); - if (cursor == fence) { - throw new NoSuchElementException(); - } - T result = elements[cursor]; - // This check doesn't catch all possible comodifications, - // but does catch the ones that corrupt traversal - if (tail != fence || result == null) { - throw new ConcurrentModificationException(); - } - lastRet = cursor; - cursor = cursor + 1 & elements.length - 1; - return result; - } - - @Override - public void remove() { - ensureAccessible(); - if (lastRet < 0) { - throw new IllegalStateException(); - } - if (delete(lastRet)) { // if left-shifted, undo increment in next() - cursor = cursor - 1 & elements.length - 1; - fence = tail; - } - lastRet = -1; - } - } -} diff --git a/buffer/src/main/java/io/netty/buffer/EmptyByteBuf.java b/buffer/src/main/java/io/netty/buffer/EmptyByteBuf.java index 07745ec127..dcf152508d 100644 --- a/buffer/src/main/java/io/netty/buffer/EmptyByteBuf.java +++ b/buffer/src/main/java/io/netty/buffer/EmptyByteBuf.java @@ -800,16 +800,6 @@ public final class EmptyByteBuf implements ByteBuf { return toString(charset); } - @Override - public ByteBuf suspendIntermediaryDeallocations() { - return this; - } - - @Override - public ByteBuf resumeIntermediaryDeallocations() { - return this; - } - @Override public int hashCode() { return 0; @@ -830,11 +820,6 @@ public final class EmptyByteBuf implements ByteBuf { return str; } - @Override - public BufType type() { - return BufType.BYTE; - } - @Override public boolean isReadable(int size) { checkLength(size); diff --git a/buffer/src/main/java/io/netty/buffer/FilteredMessageBuf.java b/buffer/src/main/java/io/netty/buffer/FilteredMessageBuf.java deleted file mode 100644 index 496814db08..0000000000 --- a/buffer/src/main/java/io/netty/buffer/FilteredMessageBuf.java +++ /dev/null @@ -1,229 +0,0 @@ -/* - * Copyright 2013 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.util.Collection; -import java.util.Iterator; - -public abstract class FilteredMessageBuf implements MessageBuf { - - protected final MessageBuf buf; - - @SuppressWarnings("unchecked") - protected FilteredMessageBuf(MessageBuf> buf) { - if (buf == null) { - throw new NullPointerException("buf"); - } - this.buf = (MessageBuf) buf; - } - - protected abstract Object filter(Object msg); - - @Override - public int drainTo(Collection super Object> c) { - return buf.drainTo(c); - } - - @Override - public int drainTo(Collection super Object> c, int maxElements) { - return buf.drainTo(c, maxElements); - } - - @Override - public BufType type() { - return buf.type(); - } - - @Override - public int maxCapacity() { - return buf.maxCapacity(); - } - - @Override - public boolean isReadable() { - return buf.isReadable(); - } - - @Override - public boolean isReadable(int size) { - return buf.isReadable(size); - } - - @Override - public boolean isWritable() { - return buf.isWritable(); - } - - @Override - public boolean isWritable(int size) { - return buf.isWritable(size); - } - - @Override - public boolean add(Object e) { - if (e == null) { - throw new NullPointerException("e"); - } - - e = filter(e); - ensureNonNull(e); - - return buf.add(e); - } - - @Override - public boolean offer(Object e) { - if (e == null) { - throw new NullPointerException("e"); - } - - e = filter(e); - ensureNonNull(e); - - return buf.offer(e); - } - - private void ensureNonNull(Object e) { - if (e == null) { - throw new IllegalStateException(getClass().getSimpleName() + ".filter() returned null"); - } - } - - @Override - public Object remove() { - return buf.remove(); - } - - @Override - public Object poll() { - return buf.poll(); - } - - @Override - public Object element() { - return buf.element(); - } - - @Override - public Object peek() { - return buf.peek(); - } - - @Override - public int size() { - return buf.size(); - } - - @Override - public boolean isEmpty() { - return buf.isEmpty(); - } - - @Override - public boolean contains(Object o) { - return buf.contains(o); - } - - @Override - public Iterator iterator() { - return buf.iterator(); - } - - @Override - public Object[] toArray() { - return buf.toArray(); - } - - @Override - public T[] toArray(T[] a) { - return buf.toArray(a); - } - - @Override - public boolean remove(Object o) { - return buf.remove(o); - } - - @Override - public boolean containsAll(Collection> c) { - return buf.containsAll(c); - } - - @Override - public boolean addAll(Collection> c) { - int i = 0; - boolean added = false; - for (Object e: c) { - if (e == null) { - throw new NullPointerException("c[" + i + ']'); - } - - e = filter(e); - ensureNonNull(e); - added |= buf.add(e); - } - return added; - } - - @Override - public boolean removeAll(Collection> c) { - return buf.removeAll(c); - } - - @Override - public boolean retainAll(Collection> c) { - return buf.retainAll(c); - } - - @Override - public void clear() { - buf.clear(); - } - - @Override - public int refCnt() { - return buf.refCnt(); - } - - @Override - public MessageBuf retain() { - buf.retain(); - return this; - } - - @Override - public MessageBuf retain(int increment) { - buf.retain(increment); - return this; - } - - @Override - public boolean release() { - return buf.release(); - } - - @Override - public boolean release(int decrement) { - return buf.release(decrement); - } - - @Override - public String toString() { - return getClass().getSimpleName() + '(' + buf + ')'; - } -} - diff --git a/buffer/src/main/java/io/netty/buffer/MessageBuf.java b/buffer/src/main/java/io/netty/buffer/MessageBuf.java deleted file mode 100644 index e5d47df8e7..0000000000 --- a/buffer/src/main/java/io/netty/buffer/MessageBuf.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright 2012 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.util.Collection; -import java.util.Queue; - -/** - * Buf which operates on messages. - * - * @param the type of the messages that are hold by this {@link MessageBuf} - */ -public interface MessageBuf extends Buf, Queue { - - /** - * Drain the content of the {@link MessageBuf} to the given {@link Collection}. - * - * @param c the {@link Collection} to drain the content to - * @return number the number of objects which was transfered - */ - int drainTo(Collection super T> c); - - /** - * Drain the content of the {@link MessageBuf} to the given {@link Collection}. - * - * @param c the {@link Collection} to drain the content to - * @param maxElements the max number of elements to drain - * @return number the number of objects which was transfered - */ - int drainTo(Collection super T> c, int maxElements); - - @Override - MessageBuf retain(int increment); - - @Override - MessageBuf retain(); -} diff --git a/buffer/src/main/java/io/netty/buffer/PooledByteBuf.java b/buffer/src/main/java/io/netty/buffer/PooledByteBuf.java index 1e67c88c44..153c3475c9 100644 --- a/buffer/src/main/java/io/netty/buffer/PooledByteBuf.java +++ b/buffer/src/main/java/io/netty/buffer/PooledByteBuf.java @@ -20,8 +20,6 @@ import io.netty.util.ResourceLeak; import java.nio.ByteBuffer; import java.nio.ByteOrder; -import java.util.ArrayDeque; -import java.util.Queue; abstract class PooledByteBuf extends AbstractReferenceCountedByteBuf { @@ -35,7 +33,6 @@ abstract class PooledByteBuf extends AbstractReferenceCountedByteBuf { private int maxLength; private ByteBuffer tmpNioBuf; - private Queue> suspendedDeallocations; protected PooledByteBuf(int maxCapacity) { super(maxCapacity); @@ -108,13 +105,7 @@ abstract class PooledByteBuf extends AbstractReferenceCountedByteBuf { } // Reallocation required. - if (suspendedDeallocations == null) { - chunk.arena.reallocate(this, newCapacity, true); - } else { - Allocation old = new Allocation(chunk, handle); - chunk.arena.reallocate(this, newCapacity, false); - suspendedDeallocations.add(old); - } + chunk.arena.reallocate(this, newCapacity, true); return this; } @@ -143,38 +134,9 @@ abstract class PooledByteBuf extends AbstractReferenceCountedByteBuf { protected abstract ByteBuffer newInternalNioBuffer(T memory); - @Override - public final ByteBuf suspendIntermediaryDeallocations() { - ensureAccessible(); - if (suspendedDeallocations == null) { - suspendedDeallocations = new ArrayDeque>(2); - } - return this; - } - - @Override - public final ByteBuf resumeIntermediaryDeallocations() { - if (suspendedDeallocations == null) { - return this; - } - - Queue> suspendedDeallocations = this.suspendedDeallocations; - this.suspendedDeallocations = null; - - if (suspendedDeallocations.isEmpty()) { - return this; - } - - for (Allocation a: suspendedDeallocations) { - a.chunk.arena.free(a.chunk, a.handle); - } - return this; - } - @Override protected final void deallocate() { if (handle >= 0) { - resumeIntermediaryDeallocations(); final long handle = this.handle; this.handle = -1; memory = null; @@ -186,14 +148,4 @@ abstract class PooledByteBuf extends AbstractReferenceCountedByteBuf { protected final int idx(int index) { return offset + index; } - - private static final class Allocation { - final PoolChunk chunk; - final long handle; - - Allocation(PoolChunk chunk, long handle) { - this.chunk = chunk; - this.handle = handle; - } - } } diff --git a/buffer/src/main/java/io/netty/buffer/QueueBackedMessageBuf.java b/buffer/src/main/java/io/netty/buffer/QueueBackedMessageBuf.java deleted file mode 100644 index 6c193c2a3d..0000000000 --- a/buffer/src/main/java/io/netty/buffer/QueueBackedMessageBuf.java +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Copyright 2012 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.util.Collection; -import java.util.Iterator; -import java.util.Queue; - -final class QueueBackedMessageBuf extends AbstractMessageBuf { - - private Queue queue; - - QueueBackedMessageBuf(Queue queue) { - super(Integer.MAX_VALUE); - if (queue == null) { - throw new NullPointerException("queue"); - } - this.queue = queue; - } - - @Override - public boolean offer(T e) { - if (e == null) { - throw new NullPointerException("e"); - } - ensureAccessible(); - return isWritable() && queue.offer(e); - } - - @Override - public T poll() { - ensureAccessible(); - return queue.poll(); - } - - @Override - public T peek() { - ensureAccessible(); - return queue.peek(); - } - - @Override - public int size() { - return queue.size(); - } - - @Override - public boolean isEmpty() { - return queue.isEmpty(); - } - - @Override - public boolean contains(Object o) { - ensureAccessible(); - return queue.contains(o); - } - - @Override - public Iterator iterator() { - ensureAccessible(); - return queue.iterator(); - } - - @Override - public Object[] toArray() { - ensureAccessible(); - return queue.toArray(); - } - - @Override - public E[] toArray(E[] a) { - ensureAccessible(); - return queue.toArray(a); - } - - @Override - public boolean remove(Object o) { - ensureAccessible(); - return queue.remove(o); - } - - @Override - public boolean containsAll(Collection> c) { - ensureAccessible(); - return queue.containsAll(c); - } - - @Override - public boolean addAll(Collection extends T> c) { - ensureAccessible(); - return isWritable(c.size()) && queue.addAll(c); - } - - @Override - public boolean removeAll(Collection> c) { - ensureAccessible(); - return queue.removeAll(c); - } - - @Override - public boolean retainAll(Collection> c) { - ensureAccessible(); - return queue.retainAll(c); - } - - @Override - public void clear() { - ensureAccessible(); - queue.clear(); - } - - @Override - protected void deallocate() { - for (T e: queue) { - BufUtil.release(e); - } - queue = null; - } -} diff --git a/buffer/src/main/java/io/netty/buffer/ReadOnlyByteBufferBuf.java b/buffer/src/main/java/io/netty/buffer/ReadOnlyByteBufferBuf.java index dd5345d63f..83b72bea46 100644 --- a/buffer/src/main/java/io/netty/buffer/ReadOnlyByteBufferBuf.java +++ b/buffer/src/main/java/io/netty/buffer/ReadOnlyByteBufferBuf.java @@ -316,14 +316,4 @@ class ReadOnlyByteBufferBuf extends AbstractReferenceCountedByteBuf { public long memoryAddress() { throw new UnsupportedOperationException(); } - - @Override - public ByteBuf suspendIntermediaryDeallocations() { - return this; - } - - @Override - public ByteBuf resumeIntermediaryDeallocations() { - return this; - } } diff --git a/buffer/src/main/java/io/netty/buffer/SwappedByteBuf.java b/buffer/src/main/java/io/netty/buffer/SwappedByteBuf.java index a18c4dc1e4..566e0b38b0 100644 --- a/buffer/src/main/java/io/netty/buffer/SwappedByteBuf.java +++ b/buffer/src/main/java/io/netty/buffer/SwappedByteBuf.java @@ -67,11 +67,6 @@ public final class SwappedByteBuf implements ByteBuf { return buf.alloc(); } - @Override - public BufType type() { - return BufType.MESSAGE; - } - @Override public int capacity() { return buf.capacity(); @@ -245,7 +240,7 @@ public final class SwappedByteBuf implements ByteBuf { @Override public short getShort(int index) { - return BufUtil.swapShort(buf.getShort(index)); + return ByteBufUtil.swapShort(buf.getShort(index)); } @Override @@ -255,7 +250,7 @@ public final class SwappedByteBuf implements ByteBuf { @Override public int getMedium(int index) { - return BufUtil.swapMedium(buf.getMedium(index)); + return ByteBufUtil.swapMedium(buf.getMedium(index)); } @Override @@ -265,7 +260,7 @@ public final class SwappedByteBuf implements ByteBuf { @Override public int getInt(int index) { - return BufUtil.swapInt(buf.getInt(index)); + return ByteBufUtil.swapInt(buf.getInt(index)); } @Override @@ -275,7 +270,7 @@ public final class SwappedByteBuf implements ByteBuf { @Override public long getLong(int index) { - return BufUtil.swapLong(buf.getLong(index)); + return ByteBufUtil.swapLong(buf.getLong(index)); } @Override @@ -354,25 +349,25 @@ public final class SwappedByteBuf implements ByteBuf { @Override public ByteBuf setShort(int index, int value) { - buf.setShort(index, BufUtil.swapShort((short) value)); + buf.setShort(index, ByteBufUtil.swapShort((short) value)); return this; } @Override public ByteBuf setMedium(int index, int value) { - buf.setMedium(index, BufUtil.swapMedium(value)); + buf.setMedium(index, ByteBufUtil.swapMedium(value)); return this; } @Override public ByteBuf setInt(int index, int value) { - buf.setInt(index, BufUtil.swapInt(value)); + buf.setInt(index, ByteBufUtil.swapInt(value)); return this; } @Override public ByteBuf setLong(int index, long value) { - buf.setLong(index, BufUtil.swapLong(value)); + buf.setLong(index, ByteBufUtil.swapLong(value)); return this; } @@ -463,7 +458,7 @@ public final class SwappedByteBuf implements ByteBuf { @Override public short readShort() { - return BufUtil.swapShort(buf.readShort()); + return ByteBufUtil.swapShort(buf.readShort()); } @Override @@ -473,7 +468,7 @@ public final class SwappedByteBuf implements ByteBuf { @Override public int readMedium() { - return BufUtil.swapMedium(buf.readMedium()); + return ByteBufUtil.swapMedium(buf.readMedium()); } @Override @@ -483,7 +478,7 @@ public final class SwappedByteBuf implements ByteBuf { @Override public int readInt() { - return BufUtil.swapInt(buf.readInt()); + return ByteBufUtil.swapInt(buf.readInt()); } @Override @@ -493,7 +488,7 @@ public final class SwappedByteBuf implements ByteBuf { @Override public long readLong() { - return BufUtil.swapLong(buf.readLong()); + return ByteBufUtil.swapLong(buf.readLong()); } @Override @@ -588,25 +583,25 @@ public final class SwappedByteBuf implements ByteBuf { @Override public ByteBuf writeShort(int value) { - buf.writeShort(BufUtil.swapShort((short) value)); + buf.writeShort(ByteBufUtil.swapShort((short) value)); return this; } @Override public ByteBuf writeMedium(int value) { - buf.writeMedium(BufUtil.swapMedium(value)); + buf.writeMedium(ByteBufUtil.swapMedium(value)); return this; } @Override public ByteBuf writeInt(int value) { - buf.writeInt(BufUtil.swapInt(value)); + buf.writeInt(ByteBufUtil.swapInt(value)); return this; } @Override public ByteBuf writeLong(long value) { - buf.writeLong(BufUtil.swapLong(value)); + buf.writeLong(ByteBufUtil.swapLong(value)); return this; } @@ -813,18 +808,6 @@ public final class SwappedByteBuf implements ByteBuf { return buf.toString(index, length, charset); } - @Override - public ByteBuf suspendIntermediaryDeallocations() { - buf.suspendIntermediaryDeallocations(); - return this; - } - - @Override - public ByteBuf resumeIntermediaryDeallocations() { - buf.resumeIntermediaryDeallocations(); - return this; - } - @Override public int refCnt() { return buf.refCnt(); @@ -863,14 +846,14 @@ public final class SwappedByteBuf implements ByteBuf { return true; } if (obj instanceof ByteBuf) { - return BufUtil.equals(this, (ByteBuf) obj); + return ByteBufUtil.equals(this, (ByteBuf) obj); } return false; } @Override public int compareTo(ByteBuf buffer) { - return BufUtil.compare(this, buffer); + return ByteBufUtil.compare(this, buffer); } @Override diff --git a/buffer/src/main/java/io/netty/buffer/Unpooled.java b/buffer/src/main/java/io/netty/buffer/Unpooled.java index 92ae8d2186..46fce0fc3a 100644 --- a/buffer/src/main/java/io/netty/buffer/Unpooled.java +++ b/buffer/src/main/java/io/netty/buffer/Unpooled.java @@ -23,11 +23,10 @@ import java.nio.CharBuffer; import java.nio.charset.Charset; import java.util.ArrayList; import java.util.List; -import java.util.Queue; /** - * Creates a new {@link ByteBuf} or a new {@link MessageBuf} by allocating new space or by wrapping + * Creates a new {@link ByteBuf} by allocating new space or by wrapping * or copying existing byte arrays, byte buffers and a string. * * Use static import @@ -94,39 +93,6 @@ public final class Unpooled { */ public static final ByteBuf EMPTY_BUFFER = ALLOC.buffer(0, 0); - /** - * Creates a new {@link MessageBuf} with reasonably small initial capacity, which - * expands its capacity boundlessly on demand. - */ - public static MessageBuf messageBuffer() { - return new DefaultMessageBuf(); - } - - /** - * Creates a new {@link MessageBuf} with the specified {@code initialCapacity}. - */ - public static MessageBuf messageBuffer(int initialCapacity) { - return new DefaultMessageBuf(initialCapacity); - } - - /** - * Creates a new {@link MessageBuf} with the specified {@code initialCapacity} and - * {@code maxCapacity}. - */ - public static MessageBuf messageBuffer(int initialCapacity, int maxCapacity) { - return new DefaultMessageBuf(initialCapacity, maxCapacity); - } - - /** - * Creates a new {@link MessageBuf} which wraps the given {@code queue}. - */ - public static MessageBuf wrappedBuffer(Queue queue) { - if (queue instanceof MessageBuf) { - return (MessageBuf) queue; - } - return new QueueBackedMessageBuf(queue); - } - /** * Creates a new big-endian Java heap buffer with reasonably small initial capacity, which * expands its capacity boundlessly on demand. @@ -681,7 +647,7 @@ public final class Unpooled { } private static ByteBuf copiedBuffer(CharBuffer buffer, Charset charset) { - ByteBuffer dst = BufUtil.encodeString(buffer, charset); + ByteBuffer dst = ByteBufUtil.encodeString(buffer, charset); ByteBuf result = wrappedBuffer(dst.array()); result.writerIndex(dst.remaining()); return result; diff --git a/buffer/src/main/java/io/netty/buffer/UnpooledDirectByteBuf.java b/buffer/src/main/java/io/netty/buffer/UnpooledDirectByteBuf.java index b066299297..b9d49ac15a 100644 --- a/buffer/src/main/java/io/netty/buffer/UnpooledDirectByteBuf.java +++ b/buffer/src/main/java/io/netty/buffer/UnpooledDirectByteBuf.java @@ -26,8 +26,6 @@ import java.nio.ByteOrder; import java.nio.channels.ClosedChannelException; import java.nio.channels.GatheringByteChannel; import java.nio.channels.ScatteringByteChannel; -import java.util.ArrayDeque; -import java.util.Queue; /** * A NIO {@link ByteBuffer} based buffer. It is recommended to use {@link Unpooled#directBuffer(int)} @@ -43,7 +41,6 @@ public class UnpooledDirectByteBuf extends AbstractReferenceCountedByteBuf { private ByteBuffer tmpNioBuf; private int capacity; private boolean doNotFree; - private Queue suspendedDeallocations; /** * Creates a new direct buffer. @@ -111,11 +108,7 @@ public class UnpooledDirectByteBuf extends AbstractReferenceCountedByteBuf { if (doNotFree) { doNotFree = false; } else { - if (suspendedDeallocations == null) { - PlatformDependent.freeDirectBuffer(oldBuffer); - } else { - suspendedDeallocations.add(oldBuffer); - } + PlatformDependent.freeDirectBuffer(oldBuffer); } } @@ -527,37 +520,12 @@ public class UnpooledDirectByteBuf extends AbstractReferenceCountedByteBuf { this.buffer = null; - resumeIntermediaryDeallocations(); if (!doNotFree) { PlatformDependent.freeDirectBuffer(buffer); } leak.close(); } - @Override - public ByteBuf suspendIntermediaryDeallocations() { - ensureAccessible(); - if (suspendedDeallocations == null) { - suspendedDeallocations = new ArrayDeque(2); - } - return this; - } - - @Override - public ByteBuf resumeIntermediaryDeallocations() { - if (suspendedDeallocations == null) { - return this; - } - - Queue suspendedDeallocations = this.suspendedDeallocations; - this.suspendedDeallocations = null; - - for (ByteBuffer buf: suspendedDeallocations) { - PlatformDependent.freeDirectBuffer(buf); - } - return this; - } - @Override public ByteBuf unwrap() { return null; diff --git a/buffer/src/main/java/io/netty/buffer/UnpooledHeapByteBuf.java b/buffer/src/main/java/io/netty/buffer/UnpooledHeapByteBuf.java index affae8f8aa..ce70ff2f14 100644 --- a/buffer/src/main/java/io/netty/buffer/UnpooledHeapByteBuf.java +++ b/buffer/src/main/java/io/netty/buffer/UnpooledHeapByteBuf.java @@ -417,16 +417,6 @@ public class UnpooledHeapByteBuf extends AbstractReferenceCountedByteBuf { array = null; } - @Override - public ByteBuf suspendIntermediaryDeallocations() { - return this; - } - - @Override - public ByteBuf resumeIntermediaryDeallocations() { - return this; - } - @Override public ByteBuf unwrap() { return null; diff --git a/buffer/src/main/java/io/netty/buffer/UnpooledUnsafeDirectByteBuf.java b/buffer/src/main/java/io/netty/buffer/UnpooledUnsafeDirectByteBuf.java index 8875613271..3dbf665c09 100644 --- a/buffer/src/main/java/io/netty/buffer/UnpooledUnsafeDirectByteBuf.java +++ b/buffer/src/main/java/io/netty/buffer/UnpooledUnsafeDirectByteBuf.java @@ -26,8 +26,6 @@ import java.nio.ByteOrder; import java.nio.channels.ClosedChannelException; import java.nio.channels.GatheringByteChannel; import java.nio.channels.ScatteringByteChannel; -import java.util.ArrayDeque; -import java.util.Queue; /** * A NIO {@link ByteBuffer} based buffer. It is recommended to use {@link Unpooled#directBuffer(int)} @@ -46,7 +44,6 @@ public class UnpooledUnsafeDirectByteBuf extends AbstractReferenceCountedByteBuf private ByteBuffer tmpNioBuf; private int capacity; private boolean doNotFree; - private Queue suspendedDeallocations; /** * Creates a new direct buffer. @@ -114,11 +111,7 @@ public class UnpooledUnsafeDirectByteBuf extends AbstractReferenceCountedByteBuf if (doNotFree) { doNotFree = false; } else { - if (suspendedDeallocations == null) { - PlatformDependent.freeDirectBuffer(oldBuffer); - } else { - suspendedDeallocations.add(oldBuffer); - } + PlatformDependent.freeDirectBuffer(oldBuffer); } } @@ -459,37 +452,12 @@ public class UnpooledUnsafeDirectByteBuf extends AbstractReferenceCountedByteBuf this.buffer = null; - resumeIntermediaryDeallocations(); if (!doNotFree) { PlatformDependent.freeDirectBuffer(buffer); } leak.close(); } - @Override - public ByteBuf suspendIntermediaryDeallocations() { - ensureAccessible(); - if (suspendedDeallocations == null) { - suspendedDeallocations = new ArrayDeque(2); - } - return this; - } - - @Override - public ByteBuf resumeIntermediaryDeallocations() { - if (suspendedDeallocations == null) { - return this; - } - - Queue suspendedDeallocations = this.suspendedDeallocations; - this.suspendedDeallocations = null; - - for (ByteBuffer buf: suspendedDeallocations) { - PlatformDependent.freeDirectBuffer(buf); - } - return this; - } - @Override public ByteBuf unwrap() { return null; diff --git a/buffer/src/main/java/io/netty/buffer/UnreleasableByteBuf.java b/buffer/src/main/java/io/netty/buffer/UnreleasableByteBuf.java index fb8a226722..c56fc49b53 100644 --- a/buffer/src/main/java/io/netty/buffer/UnreleasableByteBuf.java +++ b/buffer/src/main/java/io/netty/buffer/UnreleasableByteBuf.java @@ -796,18 +796,6 @@ final class UnreleasableByteBuf implements ByteBuf { return buf.toString(index, length, charset); } - @Override - public ByteBuf suspendIntermediaryDeallocations() { - buf.suspendIntermediaryDeallocations(); - return this; - } - - @Override - public ByteBuf resumeIntermediaryDeallocations() { - buf.resumeIntermediaryDeallocations(); - return this; - } - @Override public int hashCode() { return buf.hashCode(); @@ -838,11 +826,6 @@ final class UnreleasableByteBuf implements ByteBuf { return this; } - @Override - public BufType type() { - return buf.type(); - } - @Override public boolean isReadable(int size) { return buf.isReadable(size); diff --git a/buffer/src/test/java/io/netty/buffer/AbstractCompositeByteBufTest.java b/buffer/src/test/java/io/netty/buffer/AbstractCompositeByteBufTest.java index 584f96a6b0..68fd19c4b3 100644 --- a/buffer/src/test/java/io/netty/buffer/AbstractCompositeByteBufTest.java +++ b/buffer/src/test/java/io/netty/buffer/AbstractCompositeByteBufTest.java @@ -142,20 +142,20 @@ public abstract class AbstractCompositeByteBufTest extends AbstractByteBufTest { a.writerIndex(a.writerIndex() + 1); b.writerIndex(b.writerIndex() + 1); assertEquals(a.writerIndex(), b.writerIndex()); - assertTrue(BufUtil.equals(a, b)); + assertTrue(ByteBufUtil.equals(a, b)); // now discard a.discardReadBytes(); b.discardReadBytes(); assertEquals(a.readerIndex(), b.readerIndex()); assertEquals(a.writerIndex(), b.writerIndex()); - assertTrue(BufUtil.equals(a, b)); + assertTrue(ByteBufUtil.equals(a, b)); a.resetReaderIndex(); b.resetReaderIndex(); assertEquals(a.readerIndex(), b.readerIndex()); a.resetWriterIndex(); b.resetWriterIndex(); assertEquals(a.writerIndex(), b.writerIndex()); - assertTrue(BufUtil.equals(a, b)); + assertTrue(ByteBufUtil.equals(a, b)); } @Test @@ -231,7 +231,7 @@ public abstract class AbstractCompositeByteBufTest extends AbstractByteBufTest { b = freeLater(wrappedBuffer( wrappedBuffer(new byte[] { 1 }).order(order), wrappedBuffer(new byte[] { 2 }).order(order))); - assertFalse(BufUtil.equals(a, b)); + assertFalse(ByteBufUtil.equals(a, b)); // Same content, same firstIndex, short length. a = freeLater(wrappedBuffer(new byte[] { 1, 2, 3 }).order(order)); @@ -239,28 +239,28 @@ public abstract class AbstractCompositeByteBufTest extends AbstractByteBufTest { wrappedBuffer(new byte[]{1}).order(order), wrappedBuffer(new byte[]{2}).order(order), wrappedBuffer(new byte[]{3}).order(order))); - assertTrue(BufUtil.equals(a, b)); + assertTrue(ByteBufUtil.equals(a, b)); // Same content, different firstIndex, short length. a = freeLater(wrappedBuffer(new byte[] { 1, 2, 3 }).order(order)); b = freeLater(wrappedBuffer( wrappedBuffer(new byte[] { 0, 1, 2, 3, 4 }, 1, 2).order(order), wrappedBuffer(new byte[] { 0, 1, 2, 3, 4 }, 3, 1).order(order))); - assertTrue(BufUtil.equals(a, b)); + assertTrue(ByteBufUtil.equals(a, b)); // Different content, same firstIndex, short length. a = freeLater(wrappedBuffer(new byte[] { 1, 2, 3 }).order(order)); b = freeLater(wrappedBuffer( wrappedBuffer(new byte[] { 1, 2 }).order(order), wrappedBuffer(new byte[] { 4 }).order(order))); - assertFalse(BufUtil.equals(a, b)); + assertFalse(ByteBufUtil.equals(a, b)); // Different content, different firstIndex, short length. a = freeLater(wrappedBuffer(new byte[] { 1, 2, 3 }).order(order)); b = freeLater(wrappedBuffer( wrappedBuffer(new byte[] { 0, 1, 2, 4, 5 }, 1, 2).order(order), wrappedBuffer(new byte[] { 0, 1, 2, 4, 5 }, 3, 1).order(order))); - assertFalse(BufUtil.equals(a, b)); + assertFalse(ByteBufUtil.equals(a, b)); // Same content, same firstIndex, long length. a = freeLater(wrappedBuffer(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }).order(order)); @@ -268,28 +268,28 @@ public abstract class AbstractCompositeByteBufTest extends AbstractByteBufTest { wrappedBuffer(new byte[] { 1, 2, 3 }).order(order), wrappedBuffer(new byte[] { 4, 5, 6 }).order(order), wrappedBuffer(new byte[] { 7, 8, 9, 10 }).order(order))); - assertTrue(BufUtil.equals(a, b)); + assertTrue(ByteBufUtil.equals(a, b)); // Same content, different firstIndex, long length. a = freeLater(wrappedBuffer(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }).order(order)); b = freeLater(wrappedBuffer( wrappedBuffer(new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}, 1, 5).order(order), wrappedBuffer(new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}, 6, 5).order(order))); - assertTrue(BufUtil.equals(a, b)); + assertTrue(ByteBufUtil.equals(a, b)); // Different content, same firstIndex, long length. a = freeLater(wrappedBuffer(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }).order(order)); b = freeLater(wrappedBuffer( wrappedBuffer(new byte[] { 1, 2, 3, 4, 6 }).order(order), wrappedBuffer(new byte[] { 7, 8, 5, 9, 10 }).order(order))); - assertFalse(BufUtil.equals(a, b)); + assertFalse(ByteBufUtil.equals(a, b)); // Different content, different firstIndex, long length. a = freeLater(wrappedBuffer(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }).order(order)); b = freeLater(wrappedBuffer( wrappedBuffer(new byte[] { 0, 1, 2, 3, 4, 6, 7, 8, 5, 9, 10, 11 }, 1, 5).order(order), wrappedBuffer(new byte[] { 0, 1, 2, 3, 4, 6, 7, 8, 5, 9, 10, 11 }, 6, 5).order(order))); - assertFalse(BufUtil.equals(a, b)); + assertFalse(ByteBufUtil.equals(a, b)); } @Test @@ -345,7 +345,7 @@ public abstract class AbstractCompositeByteBufTest extends AbstractByteBufTest { // to enable writeBytes b.writerIndex(b.writerIndex() - 1); b.writeBytes(wrappedBuffer(new byte[] { 2 }).order(order)); - assertFalse(BufUtil.equals(a, b)); + assertFalse(ByteBufUtil.equals(a, b)); // Same content, same firstIndex, short length. a = wrappedBuffer(new byte[] { 1, 2, 3 }).order(order); @@ -354,7 +354,7 @@ public abstract class AbstractCompositeByteBufTest extends AbstractByteBufTest { b.writerIndex(b.writerIndex() - 2); b.writeBytes(wrappedBuffer(new byte[] { 2 }).order(order)); b.writeBytes(wrappedBuffer(new byte[] { 3 }).order(order)); - assertTrue(BufUtil.equals(a, b)); + assertTrue(ByteBufUtil.equals(a, b)); // Same content, different firstIndex, short length. a = wrappedBuffer(new byte[] { 1, 2, 3 }).order(order); @@ -362,7 +362,7 @@ public abstract class AbstractCompositeByteBufTest extends AbstractByteBufTest { // to enable writeBytes b.writerIndex(b.writerIndex() - 1); b.writeBytes(wrappedBuffer(new byte[] { 0, 1, 2, 3, 4 }, 3, 1).order(order)); - assertTrue(BufUtil.equals(a, b)); + assertTrue(ByteBufUtil.equals(a, b)); // Different content, same firstIndex, short length. a = wrappedBuffer(new byte[] { 1, 2, 3 }).order(order); @@ -370,7 +370,7 @@ public abstract class AbstractCompositeByteBufTest extends AbstractByteBufTest { // to enable writeBytes b.writerIndex(b.writerIndex() - 1); b.writeBytes(wrappedBuffer(new byte[] { 4 }).order(order)); - assertFalse(BufUtil.equals(a, b)); + assertFalse(ByteBufUtil.equals(a, b)); // Different content, different firstIndex, short length. a = wrappedBuffer(new byte[] { 1, 2, 3 }).order(order); @@ -378,7 +378,7 @@ public abstract class AbstractCompositeByteBufTest extends AbstractByteBufTest { // to enable writeBytes b.writerIndex(b.writerIndex() - 1); b.writeBytes(wrappedBuffer(new byte[] { 0, 1, 2, 4, 5 }, 3, 1).order(order)); - assertFalse(BufUtil.equals(a, b)); + assertFalse(ByteBufUtil.equals(a, b)); // Same content, same firstIndex, long length. a = wrappedBuffer(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }).order(order); @@ -387,7 +387,7 @@ public abstract class AbstractCompositeByteBufTest extends AbstractByteBufTest { b.writerIndex(b.writerIndex() - 7); b.writeBytes(wrappedBuffer(new byte[] { 4, 5, 6 }).order(order)); b.writeBytes(wrappedBuffer(new byte[] { 7, 8, 9, 10 }).order(order)); - assertTrue(BufUtil.equals(a, b)); + assertTrue(ByteBufUtil.equals(a, b)); // Same content, different firstIndex, long length. a = wrappedBuffer(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }).order(order); @@ -395,7 +395,7 @@ public abstract class AbstractCompositeByteBufTest extends AbstractByteBufTest { // to enable writeBytes b.writerIndex(b.writerIndex() - 5); b.writeBytes(wrappedBuffer(new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}, 6, 5).order(order)); - assertTrue(BufUtil.equals(a, b)); + assertTrue(ByteBufUtil.equals(a, b)); // Different content, same firstIndex, long length. a = wrappedBuffer(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }).order(order); @@ -403,7 +403,7 @@ public abstract class AbstractCompositeByteBufTest extends AbstractByteBufTest { // to enable writeBytes b.writerIndex(b.writerIndex() - 5); b.writeBytes(wrappedBuffer(new byte[] { 7, 8, 5, 9, 10 }).order(order)); - assertFalse(BufUtil.equals(a, b)); + assertFalse(ByteBufUtil.equals(a, b)); // Different content, different firstIndex, long length. a = wrappedBuffer(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }).order(order); @@ -411,7 +411,7 @@ public abstract class AbstractCompositeByteBufTest extends AbstractByteBufTest { // to enable writeBytes b.writerIndex(b.writerIndex() - 5); b.writeBytes(wrappedBuffer(new byte[] { 0, 1, 2, 3, 4, 6, 7, 8, 5, 9, 10, 11 }, 6, 5).order(order)); - assertFalse(BufUtil.equals(a, b)); + assertFalse(ByteBufUtil.equals(a, b)); } @Test diff --git a/buffer/src/test/java/io/netty/buffer/UnpooledTest.java b/buffer/src/test/java/io/netty/buffer/UnpooledTest.java index 07859fa680..6d164e5bdc 100644 --- a/buffer/src/test/java/io/netty/buffer/UnpooledTest.java +++ b/buffer/src/test/java/io/netty/buffer/UnpooledTest.java @@ -97,7 +97,7 @@ public class UnpooledTest { for (Entry e: map.entrySet()) { assertEquals( e.getValue().intValue(), - BufUtil.hashCode(wrappedBuffer(e.getKey()))); + ByteBufUtil.hashCode(wrappedBuffer(e.getKey()))); } } @@ -108,47 +108,47 @@ public class UnpooledTest { // Different length. a = wrappedBuffer(new byte[] { 1 }); b = wrappedBuffer(new byte[] { 1, 2 }); - assertFalse(BufUtil.equals(a, b)); + assertFalse(ByteBufUtil.equals(a, b)); // Same content, same firstIndex, short length. a = wrappedBuffer(new byte[] { 1, 2, 3 }); b = wrappedBuffer(new byte[] { 1, 2, 3 }); - assertTrue(BufUtil.equals(a, b)); + assertTrue(ByteBufUtil.equals(a, b)); // Same content, different firstIndex, short length. a = wrappedBuffer(new byte[] { 1, 2, 3 }); b = wrappedBuffer(new byte[] { 0, 1, 2, 3, 4 }, 1, 3); - assertTrue(BufUtil.equals(a, b)); + assertTrue(ByteBufUtil.equals(a, b)); // Different content, same firstIndex, short length. a = wrappedBuffer(new byte[] { 1, 2, 3 }); b = wrappedBuffer(new byte[] { 1, 2, 4 }); - assertFalse(BufUtil.equals(a, b)); + assertFalse(ByteBufUtil.equals(a, b)); // Different content, different firstIndex, short length. a = wrappedBuffer(new byte[] { 1, 2, 3 }); b = wrappedBuffer(new byte[] { 0, 1, 2, 4, 5 }, 1, 3); - assertFalse(BufUtil.equals(a, b)); + assertFalse(ByteBufUtil.equals(a, b)); // Same content, same firstIndex, long length. a = wrappedBuffer(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }); b = wrappedBuffer(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }); - assertTrue(BufUtil.equals(a, b)); + assertTrue(ByteBufUtil.equals(a, b)); // Same content, different firstIndex, long length. a = wrappedBuffer(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }); b = wrappedBuffer(new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}, 1, 10); - assertTrue(BufUtil.equals(a, b)); + assertTrue(ByteBufUtil.equals(a, b)); // Different content, same firstIndex, long length. a = wrappedBuffer(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }); b = wrappedBuffer(new byte[] { 1, 2, 3, 4, 6, 7, 8, 5, 9, 10 }); - assertFalse(BufUtil.equals(a, b)); + assertFalse(ByteBufUtil.equals(a, b)); // Different content, different firstIndex, long length. a = wrappedBuffer(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }); b = wrappedBuffer(new byte[] { 0, 1, 2, 3, 4, 6, 7, 8, 5, 9, 10, 11 }, 1, 10); - assertFalse(BufUtil.equals(a, b)); + assertFalse(ByteBufUtil.equals(a, b)); } @Test @@ -174,11 +174,11 @@ public class UnpooledTest { for (int i = 0; i < expected.size(); i ++) { for (int j = 0; j < expected.size(); j ++) { if (i == j) { - assertEquals(0, BufUtil.compare(expected.get(i), expected.get(j))); + assertEquals(0, ByteBufUtil.compare(expected.get(i), expected.get(j))); } else if (i < j) { - assertTrue(BufUtil.compare(expected.get(i), expected.get(j)) < 0); + assertTrue(ByteBufUtil.compare(expected.get(i), expected.get(j)) < 0); } else { - assertTrue(BufUtil.compare(expected.get(i), expected.get(j)) > 0); + assertTrue(ByteBufUtil.compare(expected.get(i), expected.get(j)) > 0); } } } @@ -217,12 +217,12 @@ public class UnpooledTest { @Test public void testCompare2() { - assertTrue(BufUtil.compare( + assertTrue(ByteBufUtil.compare( wrappedBuffer(new byte[]{(byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF}), wrappedBuffer(new byte[]{(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00})) > 0); - assertTrue(BufUtil.compare( + assertTrue(ByteBufUtil.compare( wrappedBuffer(new byte[]{(byte) 0xFF}), wrappedBuffer(new byte[]{(byte) 0x00})) > 0); @@ -327,14 +327,14 @@ public class UnpooledTest { @Test public void testHexDump() { - assertEquals("", BufUtil.hexDump(EMPTY_BUFFER)); + assertEquals("", ByteBufUtil.hexDump(EMPTY_BUFFER)); - assertEquals("123456", BufUtil.hexDump(wrappedBuffer( + assertEquals("123456", ByteBufUtil.hexDump(wrappedBuffer( new byte[]{ 0x12, 0x34, 0x56 }))); - assertEquals("1234567890abcdef", BufUtil.hexDump(wrappedBuffer( + assertEquals("1234567890abcdef", ByteBufUtil.hexDump(wrappedBuffer( new byte[]{ 0x12, 0x34, 0x56, 0x78, (byte) 0x90, (byte) 0xAB, (byte) 0xCD, (byte) 0xEF @@ -343,8 +343,8 @@ public class UnpooledTest { @Test public void testSwapMedium() { - assertEquals(0x563412, BufUtil.swapMedium(0x123456)); - assertEquals(0x80, BufUtil.swapMedium(0x800000)); + assertEquals(0x563412, ByteBufUtil.swapMedium(0x123456)); + assertEquals(0x80, ByteBufUtil.swapMedium(0x800000)); } @Test diff --git a/codec-http/pom.xml b/codec-http/pom.xml index 979864cb7a..4e187b74c1 100644 --- a/codec-http/pom.xml +++ b/codec-http/pom.xml @@ -20,7 +20,7 @@ io.netty netty-parent - 4.0.0.Final-SNAPSHOT + 4.0.0.CR4-SNAPSHOT netty-codec-http diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/HttpClientCodec.java b/codec-http/src/main/java/io/netty/handler/codec/http/HttpClientCodec.java index a91c54efa9..3c82ebd12b 100644 --- a/codec-http/src/main/java/io/netty/handler/codec/http/HttpClientCodec.java +++ b/codec-http/src/main/java/io/netty/handler/codec/http/HttpClientCodec.java @@ -16,13 +16,10 @@ package io.netty.handler.codec.http; import io.netty.buffer.ByteBuf; -import io.netty.buffer.FilteredMessageBuf; -import io.netty.buffer.MessageBuf; import io.netty.channel.Channel; import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.ChannelInboundByteHandler; -import io.netty.channel.ChannelOutboundMessageHandler; import io.netty.channel.CombinedChannelDuplexHandler; +import io.netty.channel.MessageList; import io.netty.handler.codec.PrematureChannelClosureException; import java.util.ArrayDeque; @@ -44,8 +41,7 @@ import java.util.concurrent.atomic.AtomicLong; * @see HttpServerCodec */ public final class HttpClientCodec - extends CombinedChannelDuplexHandler - implements ChannelInboundByteHandler, ChannelOutboundMessageHandler { + extends CombinedChannelDuplexHandler { /** A queue that is used for correlating a request and a response. */ private final Queue queue = new ArrayDeque(); @@ -66,11 +62,11 @@ public final class HttpClientCodec } public void setSingleDecode(boolean singleDecode) { - decoder().setSingleDecode(singleDecode); + inboundHandler().setSingleDecode(singleDecode); } public boolean isSingleDecode() { - return decoder().isSingleDecode(); + return inboundHandler().isSingleDecode(); } /** @@ -86,29 +82,6 @@ public final class HttpClientCodec this.failOnMissingResponse = failOnMissingResponse; } - private Decoder decoder() { - return (Decoder) stateHandler(); - } - - private Encoder encoder() { - return (Encoder) operationHandler(); - } - - @Override - public ByteBuf newInboundBuffer(ChannelHandlerContext ctx) throws Exception { - return decoder().newInboundBuffer(ctx); - } - - @Override - public void discardInboundReadBytes(ChannelHandlerContext ctx) throws Exception { - decoder().discardInboundReadBytes(ctx); - } - - @Override - public MessageBuf newOutboundBuffer(ChannelHandlerContext ctx) throws Exception { - return encoder().newOutboundBuffer(ctx); - } - private final class Encoder extends HttpRequestEncoder { @Override @@ -137,7 +110,7 @@ public final class HttpClientCodec @Override protected void decode( - ChannelHandlerContext ctx, ByteBuf buffer, MessageBuf out) throws Exception { + ChannelHandlerContext ctx, ByteBuf buffer, MessageList out) throws Exception { if (done) { int readable = actualReadableBytes(); if (readable == 0) { @@ -147,16 +120,14 @@ public final class HttpClientCodec } out.add(buffer.readBytes(readable)); } else { - if (failOnMissingResponse) { - out = new FilteredMessageBuf(out) { - @Override - protected Object filter(Object msg) { - decrement(msg); - return msg; - } - }; - } + int oldSize = out.size(); super.decode(ctx, buffer, out); + if (failOnMissingResponse) { + int size = out.size(); + for (int i = oldSize; i < size; i++) { + decrement(out.get(i)); + } + } } } diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/HttpContentCompressor.java b/codec-http/src/main/java/io/netty/handler/codec/http/HttpContentCompressor.java index f319f8f581..5fcef790d0 100644 --- a/codec-http/src/main/java/io/netty/handler/codec/http/HttpContentCompressor.java +++ b/codec-http/src/main/java/io/netty/handler/codec/http/HttpContentCompressor.java @@ -15,7 +15,7 @@ */ package io.netty.handler.codec.http; -import io.netty.channel.embedded.EmbeddedByteChannel; +import io.netty.channel.embedded.EmbeddedChannel; import io.netty.handler.codec.compression.ZlibCodecFactory; import io.netty.handler.codec.compression.ZlibWrapper; import io.netty.util.internal.StringUtil; @@ -119,7 +119,7 @@ public class HttpContentCompressor extends HttpContentEncoder { return new Result( targetContentEncoding, - new EmbeddedByteChannel(ZlibCodecFactory.newZlibEncoder( + new EmbeddedChannel(ZlibCodecFactory.newZlibEncoder( wrapper, compressionLevel, windowBits, memLevel))); } diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/HttpContentDecoder.java b/codec-http/src/main/java/io/netty/handler/codec/http/HttpContentDecoder.java index 2d00bf9647..5e5ac73687 100644 --- a/codec-http/src/main/java/io/netty/handler/codec/http/HttpContentDecoder.java +++ b/codec-http/src/main/java/io/netty/handler/codec/http/HttpContentDecoder.java @@ -15,21 +15,19 @@ */ package io.netty.handler.codec.http; -import io.netty.buffer.BufUtil; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufHolder; -import io.netty.buffer.MessageBuf; +import io.netty.buffer.ByteBufUtil; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.embedded.EmbeddedByteChannel; +import io.netty.channel.MessageList; +import io.netty.channel.embedded.EmbeddedChannel; import io.netty.handler.codec.MessageToMessageDecoder; -import java.util.Collections; - /** * Decodes the content of the received {@link HttpRequest} and {@link HttpContent}. * The original content is replaced with the new content decoded by the - * {@link EmbeddedByteChannel}, which is created by {@link #newContentDecoder(String)}. + * {@link EmbeddedChannel}, which is created by {@link #newContentDecoder(String)}. * Once decoding is finished, the value of the 'Content-Encoding' * header is set to the target content encoding, as returned by {@link #getTargetContentEncoding(String)}. * Also, the 'Content-Length' header is updated to the length of the @@ -47,20 +45,20 @@ import java.util.Collections; */ public abstract class HttpContentDecoder extends MessageToMessageDecoder { - private EmbeddedByteChannel decoder; + private EmbeddedChannel decoder; private HttpMessage message; private boolean decodeStarted; private boolean continueResponse; @Override - protected void decode(ChannelHandlerContext ctx, HttpObject msg, MessageBuf out) throws Exception { + protected void decode(ChannelHandlerContext ctx, HttpObject msg, MessageList out) throws Exception { if (msg instanceof HttpResponse && ((HttpResponse) msg).getStatus().code() == 100) { if (!(msg instanceof LastHttpContent)) { continueResponse = true; } // 100-continue response must be passed through. - out.add(BufUtil.retain(msg)); + out.add(ByteBufUtil.retain(msg)); return; } @@ -69,7 +67,7 @@ public abstract class HttpContentDecoder extends MessageToMessageDecodercontentEncoding. * * @param contentEncoding the value of the {@code "Content-Encoding"} header - * @return a new {@link EmbeddedByteChannel} if the specified encoding is supported. + * @return a new {@link EmbeddedChannel} if the specified encoding is supported. * {@code null} otherwise (alternatively, you can throw an exception * to block unknown encoding). */ - protected abstract EmbeddedByteChannel newContentDecoder(String contentEncoding) throws Exception; + protected abstract EmbeddedChannel newContentDecoder(String contentEncoding) throws Exception; /** * Returns the expected content encoding of the decoded content. diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/HttpContentDecompressor.java b/codec-http/src/main/java/io/netty/handler/codec/http/HttpContentDecompressor.java index 254a483dae..e328477640 100644 --- a/codec-http/src/main/java/io/netty/handler/codec/http/HttpContentDecompressor.java +++ b/codec-http/src/main/java/io/netty/handler/codec/http/HttpContentDecompressor.java @@ -15,7 +15,7 @@ */ package io.netty.handler.codec.http; -import io.netty.channel.embedded.EmbeddedByteChannel; +import io.netty.channel.embedded.EmbeddedChannel; import io.netty.handler.codec.compression.ZlibCodecFactory; import io.netty.handler.codec.compression.ZlibWrapper; @@ -26,13 +26,13 @@ import io.netty.handler.codec.compression.ZlibWrapper; */ public class HttpContentDecompressor extends HttpContentDecoder { @Override - protected EmbeddedByteChannel newContentDecoder(String contentEncoding) throws Exception { + protected EmbeddedChannel newContentDecoder(String contentEncoding) throws Exception { if ("gzip".equalsIgnoreCase(contentEncoding) || "x-gzip".equalsIgnoreCase(contentEncoding)) { - return new EmbeddedByteChannel(ZlibCodecFactory.newZlibDecoder(ZlibWrapper.GZIP)); + return new EmbeddedChannel(ZlibCodecFactory.newZlibDecoder(ZlibWrapper.GZIP)); } if ("deflate".equalsIgnoreCase(contentEncoding) || "x-deflate".equalsIgnoreCase(contentEncoding)) { // To be strict, 'deflate' means ZLIB, but some servers were not implemented correctly. - return new EmbeddedByteChannel(ZlibCodecFactory.newZlibDecoder(ZlibWrapper.ZLIB_OR_NONE)); + return new EmbeddedChannel(ZlibCodecFactory.newZlibDecoder(ZlibWrapper.ZLIB_OR_NONE)); } // 'identity' or unsupported diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/HttpContentEncoder.java b/codec-http/src/main/java/io/netty/handler/codec/http/HttpContentEncoder.java index d6be9c34c8..fb5b46c19a 100644 --- a/codec-http/src/main/java/io/netty/handler/codec/http/HttpContentEncoder.java +++ b/codec-http/src/main/java/io/netty/handler/codec/http/HttpContentEncoder.java @@ -15,25 +15,24 @@ */ package io.netty.handler.codec.http; -import io.netty.buffer.BufUtil; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufHolder; -import io.netty.buffer.MessageBuf; +import io.netty.buffer.ByteBufUtil; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.embedded.EmbeddedByteChannel; +import io.netty.channel.MessageList; +import io.netty.channel.embedded.EmbeddedChannel; import io.netty.handler.codec.MessageToMessageCodec; import io.netty.handler.codec.http.HttpHeaders.Names; import io.netty.handler.codec.http.HttpHeaders.Values; import java.util.ArrayDeque; -import java.util.Collections; import java.util.Queue; /** * Encodes the content of the outbound {@link HttpResponse} and {@link HttpContent}. * The original content is replaced with the new content encoded by the - * {@link EmbeddedByteChannel}, which is created by {@link #beginEncode(HttpResponse, String)}. + * {@link EmbeddedChannel}, which is created by {@link #beginEncode(HttpResponse, String)}. * Once encoding is finished, the value of the 'Content-Encoding' header * is set to the target content encoding, as returned by * {@link #beginEncode(HttpResponse, String)}. @@ -62,7 +61,7 @@ public abstract class HttpContentEncoder extends MessageToMessageCodec acceptEncodingQueue = new ArrayDeque(); private String acceptEncoding; - private EmbeddedByteChannel encoder; + private EmbeddedChannel encoder; private State state = State.AWAIT_HEADERS; @Override @@ -71,18 +70,18 @@ public abstract class HttpContentEncoder extends MessageToMessageCodec out) + protected void decode(ChannelHandlerContext ctx, HttpRequest msg, MessageList out) throws Exception { String acceptedEncoding = msg.headers().get(HttpHeaders.Names.ACCEPT_ENCODING); if (acceptedEncoding == null) { acceptedEncoding = HttpHeaders.Values.IDENTITY; } acceptEncodingQueue.add(acceptedEncoding); - out.add(BufUtil.retain(msg)); + out.add(ByteBufUtil.retain(msg)); } @Override - protected void encode(ChannelHandlerContext ctx, HttpObject msg, MessageBuf out) throws Exception { + protected void encode(ChannelHandlerContext ctx, HttpObject msg, MessageList out) throws Exception { final boolean isFull = msg instanceof HttpResponse && msg instanceof LastHttpContent; switch (state) { case AWAIT_HEADERS: { @@ -93,7 +92,7 @@ public abstract class HttpContentEncoder extends MessageToMessageCodec { } @Override - protected void decode(ChannelHandlerContext ctx, HttpObject msg, MessageBuf out) throws Exception { + protected void decode(ChannelHandlerContext ctx, HttpObject msg, MessageList out) throws Exception { FullHttpMessage currentMessage = this.currentMessage; if (msg instanceof HttpMessage) { @@ -129,7 +129,7 @@ public class HttpObjectAggregator extends MessageToMessageDecoder { if (!m.getDecoderResult().isSuccess()) { removeTransferEncodingChunked(m); this.currentMessage = null; - out.add(BufUtil.retain(m)); + out.add(ByteBufUtil.retain(m)); return; } if (msg instanceof HttpRequest) { diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/HttpObjectDecoder.java b/codec-http/src/main/java/io/netty/handler/codec/http/HttpObjectDecoder.java index c30eabe9ef..f1100fe0e0 100644 --- a/codec-http/src/main/java/io/netty/handler/codec/http/HttpObjectDecoder.java +++ b/codec-http/src/main/java/io/netty/handler/codec/http/HttpObjectDecoder.java @@ -16,10 +16,10 @@ package io.netty.handler.codec.http; import io.netty.buffer.ByteBuf; -import io.netty.buffer.MessageBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelPipeline; +import io.netty.channel.MessageList; import io.netty.handler.codec.DecoderResult; import io.netty.handler.codec.ReplayingDecoder; import io.netty.handler.codec.TooLongFrameException; @@ -168,7 +168,7 @@ public abstract class HttpObjectDecoder extends ReplayingDecoder out) throws Exception { + protected void decode(ChannelHandlerContext ctx, ByteBuf buffer, MessageList out) throws Exception { switch (state()) { case SKIP_CONTROL_CHARS: { try { @@ -449,7 +449,7 @@ public abstract class HttpObjectDecoder extends ReplayingDecoder out) { + private void reset(MessageList out) { if (out != null) { HttpMessage message = this.message; ByteBuf content = this.content; @@ -500,7 +500,7 @@ public abstract class HttpObjectDecoder extends ReplayingDecoder out) { + private void readFixedLengthContent(ByteBuf buffer, MessageList out) { //we have a content-length so we just read the correct number of bytes long length = HttpHeaders.getContentLength(message, -1); assert length <= Integer.MAX_VALUE; diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/HttpObjectEncoder.java b/codec-http/src/main/java/io/netty/handler/codec/http/HttpObjectEncoder.java index bdb7cbbf40..edcaf7c036 100644 --- a/codec-http/src/main/java/io/netty/handler/codec/http/HttpObjectEncoder.java +++ b/codec-http/src/main/java/io/netty/handler/codec/http/HttpObjectEncoder.java @@ -40,7 +40,7 @@ import static io.netty.handler.codec.http.HttpConstants.*; */ public abstract class HttpObjectEncoder extends MessageToByteEncoder { private static final byte[] CRLF = { CR, LF }; - private static final byte[] CRLF_END = { CR, LF, 0 }; + private static final byte[] ZERO_CRLF = { '0', CR, LF }; private static final byte[] HEADER_SEPARATOR = { COLON , SP }; private static final int ST_INIT = 0; private static final int ST_CONTENT_NON_CHUNK = 1; @@ -93,7 +93,7 @@ public abstract class HttpObjectEncoder extends MessageTo } if (chunk instanceof LastHttpContent) { - out.writeBytes(CRLF_END); + out.writeBytes(ZERO_CRLF); encodeTrailingHeaders(out, (LastHttpContent) chunk); out.writeBytes(CRLF); diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/HttpServerCodec.java b/codec-http/src/main/java/io/netty/handler/codec/http/HttpServerCodec.java index 2018362ba4..eabe8a1e8b 100644 --- a/codec-http/src/main/java/io/netty/handler/codec/http/HttpServerCodec.java +++ b/codec-http/src/main/java/io/netty/handler/codec/http/HttpServerCodec.java @@ -15,11 +15,6 @@ */ package io.netty.handler.codec.http; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.MessageBuf; -import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.ChannelInboundByteHandler; -import io.netty.channel.ChannelOutboundMessageHandler; import io.netty.channel.CombinedChannelDuplexHandler; @@ -30,8 +25,7 @@ import io.netty.channel.CombinedChannelDuplexHandler; * @see HttpClientCodec */ public final class HttpServerCodec - extends CombinedChannelDuplexHandler - implements ChannelInboundByteHandler, ChannelOutboundMessageHandler { + extends CombinedChannelDuplexHandler { /** * Creates a new instance with the default decoder options @@ -48,27 +42,4 @@ public final class HttpServerCodec public HttpServerCodec(int maxInitialLineLength, int maxHeaderSize, int maxChunkSize) { super(new HttpRequestDecoder(maxInitialLineLength, maxHeaderSize, maxChunkSize), new HttpResponseEncoder()); } - - private HttpRequestDecoder decoder() { - return (HttpRequestDecoder) stateHandler(); - } - - private HttpResponseEncoder encoder() { - return (HttpResponseEncoder) operationHandler(); - } - - @Override - public ByteBuf newInboundBuffer(ChannelHandlerContext ctx) throws Exception { - return decoder().newInboundBuffer(ctx); - } - - @Override - public void discardInboundReadBytes(ChannelHandlerContext ctx) throws Exception { - decoder().discardInboundReadBytes(ctx); - } - - @Override - public MessageBuf newOutboundBuffer(ChannelHandlerContext ctx) throws Exception { - return encoder().newOutboundBuffer(ctx); - } } diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/multipart/HttpPostRequestDecoder.java b/codec-http/src/main/java/io/netty/handler/codec/http/multipart/HttpPostRequestDecoder.java index 5057ae92e5..fb65bdfffc 100644 --- a/codec-http/src/main/java/io/netty/handler/codec/http/multipart/HttpPostRequestDecoder.java +++ b/codec-http/src/main/java/io/netty/handler/codec/http/multipart/HttpPostRequestDecoder.java @@ -15,7 +15,6 @@ */ package io.netty.handler.codec.http.multipart; -import io.netty.buffer.BufUtil; import io.netty.buffer.ByteBuf; import io.netty.handler.codec.DecoderException; import io.netty.handler.codec.http.HttpConstants; diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/multipart/HttpPostRequestEncoder.java b/codec-http/src/main/java/io/netty/handler/codec/http/multipart/HttpPostRequestEncoder.java index 41ede3403e..adf46f5f24 100644 --- a/codec-http/src/main/java/io/netty/handler/codec/http/multipart/HttpPostRequestEncoder.java +++ b/codec-http/src/main/java/io/netty/handler/codec/http/multipart/HttpPostRequestEncoder.java @@ -16,7 +16,7 @@ package io.netty.handler.codec.http.multipart; import io.netty.buffer.ByteBuf; -import io.netty.buffer.MessageBuf; +import io.netty.channel.MessageList; import io.netty.handler.codec.DecoderResult; import io.netty.handler.codec.http.DefaultFullHttpRequest; import io.netty.handler.codec.http.DefaultHttpContent; @@ -943,7 +943,7 @@ public class HttpPostRequestEncoder implements ChunkedMessageInput * if the encoding is in error */ @Override - public boolean readChunk(MessageBuf buffer) throws ErrorDataEncoderException { + public boolean readChunk(MessageList buffer) throws ErrorDataEncoderException { if (isLastChunkSent) { return false; } else { diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocket00FrameDecoder.java b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocket00FrameDecoder.java index d1d486f2d2..c5bd9b02d2 100644 --- a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocket00FrameDecoder.java +++ b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocket00FrameDecoder.java @@ -16,8 +16,8 @@ package io.netty.handler.codec.http.websocketx; import io.netty.buffer.ByteBuf; -import io.netty.buffer.MessageBuf; import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.MessageList; import io.netty.handler.codec.ReplayingDecoder; import io.netty.handler.codec.TooLongFrameException; @@ -50,7 +50,7 @@ public class WebSocket00FrameDecoder extends ReplayingDecoder { } @Override - protected void decode(ChannelHandlerContext ctx, ByteBuf in, MessageBuf out) throws Exception { + protected void decode(ChannelHandlerContext ctx, ByteBuf in, MessageList out) throws Exception { // Discard all data received if closing handshake was received before. if (receivedClosingHandshake) { in.skipBytes(actualReadableBytes()); diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocket08FrameDecoder.java b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocket08FrameDecoder.java index 2e0be188d7..8032d5ec48 100644 --- a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocket08FrameDecoder.java +++ b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocket08FrameDecoder.java @@ -54,9 +54,10 @@ package io.netty.handler.codec.http.websocketx; import io.netty.buffer.ByteBuf; -import io.netty.buffer.MessageBuf; +import io.netty.buffer.Unpooled; import io.netty.channel.ChannelFutureListener; import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.MessageList; import io.netty.handler.codec.CorruptedFrameException; import io.netty.handler.codec.ReplayingDecoder; import io.netty.handler.codec.TooLongFrameException; @@ -89,6 +90,7 @@ public class WebSocket08FrameDecoder extends ReplayingDecoder out) throws Exception { + protected void decode(ChannelHandlerContext ctx, ByteBuf in, MessageList out) throws Exception { // Discard all data received if closing handshake was received before. if (receivedClosingHandshake) { @@ -126,248 +128,267 @@ public class WebSocket08FrameDecoder extends ReplayingDecoder> 4; - frameOpcode = b & 0x0F; + // FIN, RSV, OPCODE + byte b = in.readByte(); + frameFinalFlag = (b & 0x80) != 0; + frameRsv = (b & 0x70) >> 4; + frameOpcode = b & 0x0F; - if (logger.isDebugEnabled()) { - logger.debug("Decoding WebSocket Frame opCode={}", frameOpcode); - } + if (logger.isDebugEnabled()) { + logger.debug("Decoding WebSocket Frame opCode={}", frameOpcode); + } - // MASK, PAYLOAD LEN 1 - b = in.readByte(); - boolean frameMasked = (b & 0x80) != 0; - int framePayloadLen1 = b & 0x7F; + // MASK, PAYLOAD LEN 1 + b = in.readByte(); + boolean frameMasked = (b & 0x80) != 0; + int framePayloadLen1 = b & 0x7F; - if (frameRsv != 0 && !allowExtensions) { - protocolViolation(ctx, "RSV != 0 and no extension negotiated, RSV:" + frameRsv); - return; - } - - if (maskedPayload && !frameMasked) { - protocolViolation(ctx, "unmasked client to server frame"); - return; - } - if (frameOpcode > 7) { // control frame (have MSB in opcode set) - - // control frames MUST NOT be fragmented - if (!frameFinalFlag) { - protocolViolation(ctx, "fragmented control frame"); + if (frameRsv != 0 && !allowExtensions) { + protocolViolation(ctx, "RSV != 0 and no extension negotiated, RSV:" + frameRsv); return; } - // control frames MUST have payload 125 octets or less - if (framePayloadLen1 > 125) { - protocolViolation(ctx, "control frame with payload length > 125 octets"); + if (maskedPayload && !frameMasked) { + protocolViolation(ctx, "unmasked client to server frame"); return; } + if (frameOpcode > 7) { // control frame (have MSB in opcode set) - // check for reserved control frame opcodes - if (!(frameOpcode == OPCODE_CLOSE || frameOpcode == OPCODE_PING || frameOpcode == OPCODE_PONG)) { - protocolViolation(ctx, "control frame using reserved opcode " + frameOpcode); - return; - } + // control frames MUST NOT be fragmented + if (!frameFinalFlag) { + protocolViolation(ctx, "fragmented control frame"); + return; + } - // close frame : if there is a body, the first two bytes of the - // body MUST be a 2-byte unsigned integer (in network byte - // order) representing a getStatus code - if (frameOpcode == 8 && framePayloadLen1 == 1) { - protocolViolation(ctx, "received close control frame with payload len 1"); - return; - } - } else { // data frame - // check for reserved data frame opcodes - if (!(frameOpcode == OPCODE_CONT || frameOpcode == OPCODE_TEXT || frameOpcode == OPCODE_BINARY)) { - protocolViolation(ctx, "data frame using reserved opcode " + frameOpcode); - return; - } + // control frames MUST have payload 125 octets or less + if (framePayloadLen1 > 125) { + protocolViolation(ctx, "control frame with payload length > 125 octets"); + return; + } - // check opcode vs message fragmentation state 1/2 - if (fragmentedFramesCount == 0 && frameOpcode == OPCODE_CONT) { - protocolViolation(ctx, "received continuation data frame outside fragmented message"); - return; - } + // check for reserved control frame opcodes + if (!(frameOpcode == OPCODE_CLOSE || frameOpcode == OPCODE_PING + || frameOpcode == OPCODE_PONG)) { + protocolViolation(ctx, "control frame using reserved opcode " + frameOpcode); + return; + } - // check opcode vs message fragmentation state 2/2 - if (fragmentedFramesCount != 0 && frameOpcode != OPCODE_CONT && frameOpcode != OPCODE_PING) { - protocolViolation(ctx, "received non-continuation data frame while inside fragmented message"); - return; - } - } + // close frame : if there is a body, the first two bytes of the + // body MUST be a 2-byte unsigned integer (in network byte + // order) representing a getStatus code + if (frameOpcode == 8 && framePayloadLen1 == 1) { + protocolViolation(ctx, "received close control frame with payload len 1"); + return; + } + } else { // data frame + // check for reserved data frame opcodes + if (!(frameOpcode == OPCODE_CONT || frameOpcode == OPCODE_TEXT + || frameOpcode == OPCODE_BINARY)) { + protocolViolation(ctx, "data frame using reserved opcode " + frameOpcode); + return; + } - // Read frame payload length - if (framePayloadLen1 == 126) { - framePayloadLength = in.readUnsignedShort(); - if (framePayloadLength < 126) { - protocolViolation(ctx, "invalid data frame length (not using minimal length encoding)"); - return; - } - } else if (framePayloadLen1 == 127) { - framePayloadLength = in.readLong(); - // TODO: check if it's bigger than 0x7FFFFFFFFFFFFFFF, Maybe - // just check if it's negative? + // check opcode vs message fragmentation state 1/2 + if (fragmentedFramesCount == 0 && frameOpcode == OPCODE_CONT) { + protocolViolation(ctx, "received continuation data frame outside fragmented message"); + return; + } - if (framePayloadLength < 65536) { - protocolViolation(ctx, "invalid data frame length (not using minimal length encoding)"); - return; - } - } else { - framePayloadLength = framePayloadLen1; - } - - if (framePayloadLength > maxFramePayloadLength) { - protocolViolation(ctx, "Max frame length of " + maxFramePayloadLength + " has been exceeded."); - return; - } - - if (logger.isDebugEnabled()) { - logger.debug("Decoding WebSocket Frame length={}", framePayloadLength); - } - - checkpoint(State.MASKING_KEY); - case MASKING_KEY: - if (maskedPayload) { - maskingKey = in.readBytes(4); - } - checkpoint(State.PAYLOAD); - case PAYLOAD: - // Sometimes, the payload may not be delivered in 1 nice packet - // We need to accumulate the data until we have it all - int rbytes = actualReadableBytes(); - ByteBuf payloadBuffer = null; - - long willHaveReadByteCount = framePayloadBytesRead + rbytes; - // logger.debug("Frame rbytes=" + rbytes + " willHaveReadByteCount=" - // + willHaveReadByteCount + " framePayloadLength=" + - // framePayloadLength); - if (willHaveReadByteCount == framePayloadLength) { - // We have all our content so proceed to process - payloadBuffer = ctx.alloc().buffer(rbytes); - payloadBuffer.writeBytes(in, rbytes); - } else if (willHaveReadByteCount < framePayloadLength) { - - // We don't have all our content so accumulate payload. - // Returning null means we will get called back - if (framePayload == null) { - framePayload = ctx.alloc().buffer(toFrameLength(framePayloadLength)); - } - framePayload.writeBytes(in, rbytes); - framePayloadBytesRead += rbytes; - - // Return null to wait for more bytes to arrive - return; - } else if (willHaveReadByteCount > framePayloadLength) { - // We have more than what we need so read up to the end of frame - // Leave the remainder in the buffer for next frame - if (framePayload == null) { - framePayload = ctx.alloc().buffer(toFrameLength(framePayloadLength)); - } - framePayload.writeBytes(in, toFrameLength(framePayloadLength - framePayloadBytesRead)); - } - - // Now we have all the data, the next checkpoint must be the next - // frame - checkpoint(State.FRAME_START); - - // Take the data that we have in this packet - if (framePayload == null) { - framePayload = payloadBuffer; - } else if (payloadBuffer != null) { - framePayload.writeBytes(payloadBuffer); - } - - // Unmask data if needed - if (maskedPayload) { - unmask(framePayload); - } - - // Processing ping/pong/close frames because they cannot be - // fragmented - if (frameOpcode == OPCODE_PING) { - out.add(new PingWebSocketFrame(frameFinalFlag, frameRsv, framePayload)); - return; - } - if (frameOpcode == OPCODE_PONG) { - out.add(new PongWebSocketFrame(frameFinalFlag, frameRsv, framePayload)); - return; - } - if (frameOpcode == OPCODE_CLOSE) { - checkCloseFrameBody(ctx, framePayload); - receivedClosingHandshake = true; - out.add(new CloseWebSocketFrame(frameFinalFlag, frameRsv, framePayload)); - return; - } - - // Processing for possible fragmented messages for text and binary - // frames - String aggregatedText = null; - if (frameFinalFlag) { - // Final frame of the sequence. Apparently ping frames are - // allowed in the middle of a fragmented message - if (frameOpcode != OPCODE_PING) { - fragmentedFramesCount = 0; - - // Check text for UTF8 correctness - if (frameOpcode == OPCODE_TEXT || fragmentedFramesText != null) { - // Check UTF-8 correctness for this payload - checkUTF8String(ctx, framePayload); - - // This does a second check to make sure UTF-8 - // correctness for entire text message - aggregatedText = fragmentedFramesText.toString(); - - fragmentedFramesText = null; + // check opcode vs message fragmentation state 2/2 + if (fragmentedFramesCount != 0 && frameOpcode != OPCODE_CONT && frameOpcode != OPCODE_PING) { + protocolViolation(ctx, + "received non-continuation data frame while inside fragmented message"); + return; } } - } else { - // Not final frame so we can expect more frames in the - // fragmented sequence - if (fragmentedFramesCount == 0) { - // First text or binary frame for a fragmented set - fragmentedFramesText = null; - if (frameOpcode == OPCODE_TEXT) { - checkUTF8String(ctx, framePayload); + + // Read frame payload length + if (framePayloadLen1 == 126) { + framePayloadLength = in.readUnsignedShort(); + if (framePayloadLength < 126) { + protocolViolation(ctx, "invalid data frame length (not using minimal length encoding)"); + return; + } + } else if (framePayloadLen1 == 127) { + framePayloadLength = in.readLong(); + // TODO: check if it's bigger than 0x7FFFFFFFFFFFFFFF, Maybe + // just check if it's negative? + + if (framePayloadLength < 65536) { + protocolViolation(ctx, "invalid data frame length (not using minimal length encoding)"); + return; } } else { - // Subsequent frames - only check if init frame is text - if (fragmentedFramesText != null) { - checkUTF8String(ctx, framePayload); - } + framePayloadLength = framePayloadLen1; } - // Increment counter - fragmentedFramesCount++; - } + if (framePayloadLength > maxFramePayloadLength) { + protocolViolation(ctx, "Max frame length of " + maxFramePayloadLength + " has been exceeded."); + return; + } - // Return the frame - if (frameOpcode == OPCODE_TEXT) { - out.add(new TextWebSocketFrame(frameFinalFlag, frameRsv, framePayload)); + if (logger.isDebugEnabled()) { + logger.debug("Decoding WebSocket Frame length={}", framePayloadLength); + } + + checkpoint(State.MASKING_KEY); + case MASKING_KEY: + if (maskedPayload) { + maskingKey = in.readBytes(4); + } + checkpoint(State.PAYLOAD); + case PAYLOAD: + // Sometimes, the payload may not be delivered in 1 nice packet + // We need to accumulate the data until we have it all + int rbytes = actualReadableBytes(); + + long willHaveReadByteCount = framePayloadBytesRead + rbytes; + // logger.debug("Frame rbytes=" + rbytes + " willHaveReadByteCount=" + // + willHaveReadByteCount + " framePayloadLength=" + + // framePayloadLength); + if (willHaveReadByteCount == framePayloadLength) { + // We have all our content so proceed to process + payloadBuffer = ctx.alloc().buffer(rbytes); + payloadBuffer.writeBytes(in, rbytes); + } else if (willHaveReadByteCount < framePayloadLength) { + + // We don't have all our content so accumulate payload. + // Returning null means we will get called back + if (framePayload == null) { + framePayload = ctx.alloc().buffer(toFrameLength(framePayloadLength)); + } + framePayload.writeBytes(in, rbytes); + framePayloadBytesRead += rbytes; + + // Return null to wait for more bytes to arrive + return; + } else if (willHaveReadByteCount > framePayloadLength) { + // We have more than what we need so read up to the end of frame + // Leave the remainder in the buffer for next frame + if (framePayload == null) { + framePayload = ctx.alloc().buffer(toFrameLength(framePayloadLength)); + } + framePayload.writeBytes(in, toFrameLength(framePayloadLength - framePayloadBytesRead)); + } + + // Now we have all the data, the next checkpoint must be the next + // frame + checkpoint(State.FRAME_START); + + // Take the data that we have in this packet + if (framePayload == null) { + framePayload = payloadBuffer; + } else if (payloadBuffer != null) { + framePayload.writeBytes(payloadBuffer); + } + + // Unmask data if needed + if (maskedPayload) { + unmask(framePayload); + } + + // Processing ping/pong/close frames because they cannot be + // fragmented + if (frameOpcode == OPCODE_PING) { + out.add(new PingWebSocketFrame(frameFinalFlag, frameRsv, framePayload)); + return; + } + if (frameOpcode == OPCODE_PONG) { + out.add(new PongWebSocketFrame(frameFinalFlag, frameRsv, framePayload)); + return; + } + if (frameOpcode == OPCODE_CLOSE) { + checkCloseFrameBody(ctx, framePayload); + receivedClosingHandshake = true; + out.add(new CloseWebSocketFrame(frameFinalFlag, frameRsv, framePayload)); + return; + } + + // Processing for possible fragmented messages for text and binary + // frames + String aggregatedText = null; + if (frameFinalFlag) { + // Final frame of the sequence. Apparently ping frames are + // allowed in the middle of a fragmented message + if (frameOpcode != OPCODE_PING) { + fragmentedFramesCount = 0; + + // Check text for UTF8 correctness + if (frameOpcode == OPCODE_TEXT || fragmentedFramesText != null) { + // Check UTF-8 correctness for this payload + checkUTF8String(ctx, framePayload); + + // This does a second check to make sure UTF-8 + // correctness for entire text message + aggregatedText = fragmentedFramesText.toString(); + + fragmentedFramesText = null; + } + } + } else { + // Not final frame so we can expect more frames in the + // fragmented sequence + if (fragmentedFramesCount == 0) { + // First text or binary frame for a fragmented set + fragmentedFramesText = null; + if (frameOpcode == OPCODE_TEXT) { + checkUTF8String(ctx, framePayload); + } + } else { + // Subsequent frames - only check if init frame is text + if (fragmentedFramesText != null) { + checkUTF8String(ctx, framePayload); + } + } + + // Increment counter + fragmentedFramesCount++; + } + + // Return the frame + if (frameOpcode == OPCODE_TEXT) { + out.add(new TextWebSocketFrame(frameFinalFlag, frameRsv, framePayload)); + return; + } else if (frameOpcode == OPCODE_BINARY) { + out.add(new BinaryWebSocketFrame(frameFinalFlag, frameRsv, framePayload)); + return; + } else if (frameOpcode == OPCODE_CONT) { + out.add(new ContinuationWebSocketFrame(frameFinalFlag, frameRsv, framePayload, aggregatedText)); + return; + } else { + throw new UnsupportedOperationException("Cannot decode web socket frame with opcode: " + + frameOpcode); + } + case CORRUPT: + // If we don't keep reading Netty will throw an exception saying + // we can't return null if no bytes read and state not changed. + in.readByte(); return; - } else if (frameOpcode == OPCODE_BINARY) { - out.add(new BinaryWebSocketFrame(frameFinalFlag, frameRsv, framePayload)); - return; - } else if (frameOpcode == OPCODE_CONT) { - out.add(new ContinuationWebSocketFrame(frameFinalFlag, frameRsv, framePayload, aggregatedText)); - return; - } else { - throw new UnsupportedOperationException("Cannot decode web socket frame with opcode: " - + frameOpcode); + default: + throw new Error("Shouldn't reach here."); + } + } catch (Exception e) { + if (payloadBuffer != null) { + if (payloadBuffer.refCnt() > 0) { + payloadBuffer.release(); } - case CORRUPT: - // If we don't keep reading Netty will throw an exception saying - // we can't return null if no bytes read and state not changed. - in.readByte(); - return; - default: - throw new Error("Shouldn't reach here."); + payloadBuffer = null; + } + if (framePayload != null) { + if (framePayload.refCnt() > 0) { + framePayload.release(); + } + framePayload = null; + } + throw e; } } @@ -380,7 +401,7 @@ public class WebSocket08FrameDecoder extends ReplayingDecoder newWebSocketEncoder(); + protected abstract ChannelOutboundHandler newWebSocketEncoder(); } diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketClientHandshaker00.java b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketClientHandshaker00.java index 4fc2211625..b8422ac00c 100644 --- a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketClientHandshaker00.java +++ b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketClientHandshaker00.java @@ -17,8 +17,8 @@ package io.netty.handler.codec.http.websocketx; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; -import io.netty.channel.ChannelInboundByteHandler; -import io.netty.channel.ChannelOutboundMessageHandler; +import io.netty.channel.ChannelInboundHandler; +import io.netty.channel.ChannelOutboundHandler; import io.netty.handler.codec.http.DefaultFullHttpRequest; import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.FullHttpResponse; @@ -252,12 +252,12 @@ public class WebSocketClientHandshaker00 extends WebSocketClientHandshaker { } @Override - protected ChannelInboundByteHandler newWebsocketDecoder() { + protected ChannelInboundHandler newWebsocketDecoder() { return new WebSocket00FrameDecoder(maxFramePayloadLength()); } @Override - protected ChannelOutboundMessageHandler newWebSocketEncoder() { + protected ChannelOutboundHandler newWebSocketEncoder() { return new WebSocket00FrameEncoder(); } } diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketClientHandshaker07.java b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketClientHandshaker07.java index 205ba762fe..b85c654696 100644 --- a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketClientHandshaker07.java +++ b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketClientHandshaker07.java @@ -15,8 +15,8 @@ */ package io.netty.handler.codec.http.websocketx; -import io.netty.channel.ChannelInboundByteHandler; -import io.netty.channel.ChannelOutboundMessageHandler; +import io.netty.channel.ChannelInboundHandler; +import io.netty.channel.ChannelOutboundHandler; import io.netty.handler.codec.http.DefaultFullHttpRequest; import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.FullHttpResponse; @@ -191,12 +191,12 @@ public class WebSocketClientHandshaker07 extends WebSocketClientHandshaker { } @Override - protected ChannelInboundByteHandler newWebsocketDecoder() { + protected ChannelInboundHandler newWebsocketDecoder() { return new WebSocket07FrameDecoder(false, allowExtensions, maxFramePayloadLength()); } @Override - protected ChannelOutboundMessageHandler newWebSocketEncoder() { + protected ChannelOutboundHandler newWebSocketEncoder() { return new WebSocket07FrameEncoder(true); } } diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketClientHandshaker08.java b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketClientHandshaker08.java index bb66d369b6..93b2132aa2 100644 --- a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketClientHandshaker08.java +++ b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketClientHandshaker08.java @@ -15,8 +15,8 @@ */ package io.netty.handler.codec.http.websocketx; -import io.netty.channel.ChannelInboundByteHandler; -import io.netty.channel.ChannelOutboundMessageHandler; +import io.netty.channel.ChannelInboundHandler; +import io.netty.channel.ChannelOutboundHandler; import io.netty.handler.codec.http.DefaultFullHttpRequest; import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.FullHttpResponse; @@ -191,12 +191,12 @@ public class WebSocketClientHandshaker08 extends WebSocketClientHandshaker { } @Override - protected ChannelInboundByteHandler newWebsocketDecoder() { + protected ChannelInboundHandler newWebsocketDecoder() { return new WebSocket08FrameDecoder(false, allowExtensions, maxFramePayloadLength()); } @Override - protected ChannelOutboundMessageHandler newWebSocketEncoder() { + protected ChannelOutboundHandler newWebSocketEncoder() { return new WebSocket08FrameEncoder(true); } } diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketClientHandshaker13.java b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketClientHandshaker13.java index 9f2c4ca336..b12ac03dde 100644 --- a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketClientHandshaker13.java +++ b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketClientHandshaker13.java @@ -15,8 +15,8 @@ */ package io.netty.handler.codec.http.websocketx; -import io.netty.channel.ChannelInboundByteHandler; -import io.netty.channel.ChannelOutboundMessageHandler; +import io.netty.channel.ChannelInboundHandler; +import io.netty.channel.ChannelOutboundHandler; import io.netty.handler.codec.http.DefaultFullHttpRequest; import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.FullHttpResponse; @@ -191,12 +191,12 @@ public class WebSocketClientHandshaker13 extends WebSocketClientHandshaker { } @Override - protected ChannelInboundByteHandler newWebsocketDecoder() { + protected ChannelInboundHandler newWebsocketDecoder() { return new WebSocket13FrameDecoder(false, allowExtensions, maxFramePayloadLength()); } @Override - protected ChannelOutboundMessageHandler newWebSocketEncoder() { + protected ChannelOutboundHandler newWebSocketEncoder() { return new WebSocket13FrameEncoder(true); } } diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketClientProtocolHandler.java b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketClientProtocolHandler.java index a3d72ab96d..69d5af599f 100644 --- a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketClientProtocolHandler.java +++ b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketClientProtocolHandler.java @@ -16,8 +16,9 @@ package io.netty.handler.codec.http.websocketx; import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelInboundHandler; import io.netty.channel.ChannelPipeline; -import io.netty.channel.ChannelStateHandler; +import io.netty.channel.MessageList; import io.netty.handler.codec.http.HttpHeaders; import java.net.URI; @@ -33,7 +34,7 @@ import java.net.URI; * This implementation will establish the websocket connection once the connection to the remote server was complete. * * To know once a handshake was done you can intercept the - * {@link ChannelStateHandler#userEventTriggered(ChannelHandlerContext, Object)} and check if the event was of type + * {@link ChannelInboundHandler#userEventTriggered(ChannelHandlerContext, Object)} and check if the event was of type * {@link ClientHandshakeStateEvent#HANDSHAKE_ISSUED} or {@link ClientHandshakeStateEvent#HANDSHAKE_COMPLETE}. */ public class WebSocketClientProtocolHandler extends WebSocketProtocolHandler { @@ -128,12 +129,12 @@ public class WebSocketClientProtocolHandler extends WebSocketProtocolHandler { } @Override - public void messageReceived(ChannelHandlerContext ctx, WebSocketFrame frame) throws Exception { + protected void decode(ChannelHandlerContext ctx, WebSocketFrame frame, MessageList out) throws Exception { if (handleCloseFrames && frame instanceof CloseWebSocketFrame) { ctx.close(); return; } - super.messageReceived(ctx, frame); + super.decode(ctx, frame, out); } @Override diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketClientProtocolHandshakeHandler.java b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketClientProtocolHandshakeHandler.java index 6ba95fa736..56c3b62967 100644 --- a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketClientProtocolHandshakeHandler.java +++ b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketClientProtocolHandshakeHandler.java @@ -18,10 +18,11 @@ package io.netty.handler.codec.http.websocketx; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelFutureListener; import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.ChannelInboundMessageHandlerAdapter; +import io.netty.channel.ChannelInboundHandlerAdapter; +import io.netty.channel.MessageList; import io.netty.handler.codec.http.FullHttpResponse; -class WebSocketClientProtocolHandshakeHandler extends ChannelInboundMessageHandlerAdapter { +class WebSocketClientProtocolHandshakeHandler extends ChannelInboundHandlerAdapter { private final WebSocketClientHandshaker handshaker; public WebSocketClientProtocolHandshakeHandler(WebSocketClientHandshaker handshaker) { @@ -45,9 +46,10 @@ class WebSocketClientProtocolHandshakeHandler extends ChannelInboundMessageHandl } @Override - public void messageReceived(ChannelHandlerContext ctx, FullHttpResponse msg) throws Exception { + public void messageReceived(ChannelHandlerContext ctx, MessageList messages) throws Exception { if (!handshaker.isHandshakeComplete()) { - handshaker.finishHandshake(ctx.channel(), msg); + handshaker.finishHandshake(ctx.channel(), (FullHttpResponse) messages.get(0)); + messages.remove(0); ctx.fireUserEventTriggered( WebSocketClientProtocolHandler.ClientHandshakeStateEvent.HANDSHAKE_COMPLETE); ctx.pipeline().remove(this); diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketFrameAggregator.java b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketFrameAggregator.java index 0ff0b28ba0..739ff18e2f 100644 --- a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketFrameAggregator.java +++ b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketFrameAggregator.java @@ -17,8 +17,8 @@ package io.netty.handler.codec.http.websocketx; import io.netty.buffer.ByteBuf; import io.netty.buffer.CompositeByteBuf; -import io.netty.buffer.MessageBuf; import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.MessageList; import io.netty.handler.codec.MessageToMessageDecoder; import io.netty.handler.codec.TooLongFrameException; @@ -47,7 +47,7 @@ public class WebSocketFrameAggregator extends MessageToMessageDecoder out) throws Exception { + protected void decode(ChannelHandlerContext ctx, WebSocketFrame msg, MessageList out) throws Exception { if (currentFrame == null) { tooLongFrameFound = false; if (msg.isFinalFragment()) { diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketProtocolHandler.java b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketProtocolHandler.java index c5014ba6d7..49ca45ec86 100644 --- a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketProtocolHandler.java +++ b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketProtocolHandler.java @@ -17,12 +17,12 @@ package io.netty.handler.codec.http.websocketx; import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.ChannelInboundMessageHandlerAdapter; - -abstract class WebSocketProtocolHandler extends ChannelInboundMessageHandlerAdapter { +import io.netty.channel.MessageList; +import io.netty.handler.codec.MessageToMessageDecoder; +abstract class WebSocketProtocolHandler extends MessageToMessageDecoder { @Override - public void messageReceived(ChannelHandlerContext ctx, WebSocketFrame frame) throws Exception { + protected void decode(ChannelHandlerContext ctx, WebSocketFrame frame, MessageList out) throws Exception { if (frame instanceof PingWebSocketFrame) { frame.content().retain(); ctx.channel().write(new PongWebSocketFrame(frame.content())); @@ -33,8 +33,7 @@ abstract class WebSocketProtocolHandler extends ChannelInboundMessageHandlerAda return; } - frame.retain(); - ctx.nextInboundMessageBuffer().add(frame); + out.add(frame.retain()); } @Override diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketServerHandshaker.java b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketServerHandshaker.java index 38d00d0389..de8c88fdfe 100644 --- a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketServerHandshaker.java +++ b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketServerHandshaker.java @@ -19,8 +19,8 @@ import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelFutureListener; import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.ChannelInboundByteHandler; -import io.netty.channel.ChannelOutboundMessageHandler; +import io.netty.channel.ChannelInboundHandler; +import io.netty.channel.ChannelOutboundHandler; import io.netty.channel.ChannelPipeline; import io.netty.channel.ChannelPromise; import io.netty.handler.codec.http.FullHttpRequest; @@ -267,11 +267,11 @@ public abstract class WebSocketServerHandshaker { /** * Returns the decoder to use after handshake is complete. */ - protected abstract ChannelInboundByteHandler newWebsocketDecoder(); + protected abstract ChannelInboundHandler newWebsocketDecoder(); /** * Returns the encoder to use after the handshake is complete. */ - protected abstract ChannelOutboundMessageHandler newWebSocketEncoder(); + protected abstract ChannelOutboundHandler newWebSocketEncoder(); } diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketServerHandshaker00.java b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketServerHandshaker00.java index 89969fde68..73307000e3 100644 --- a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketServerHandshaker00.java +++ b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketServerHandshaker00.java @@ -19,8 +19,8 @@ import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; -import io.netty.channel.ChannelInboundByteHandler; -import io.netty.channel.ChannelOutboundMessageHandler; +import io.netty.channel.ChannelInboundHandler; +import io.netty.channel.ChannelOutboundHandler; import io.netty.channel.ChannelPromise; import io.netty.handler.codec.http.DefaultFullHttpResponse; import io.netty.handler.codec.http.FullHttpRequest; @@ -183,12 +183,12 @@ public class WebSocketServerHandshaker00 extends WebSocketServerHandshaker { } @Override - protected ChannelInboundByteHandler newWebsocketDecoder() { + protected ChannelInboundHandler newWebsocketDecoder() { return new WebSocket00FrameDecoder(maxFramePayloadLength()); } @Override - protected ChannelOutboundMessageHandler newWebSocketEncoder() { + protected ChannelOutboundHandler newWebSocketEncoder() { return new WebSocket00FrameEncoder(); } } diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketServerHandshaker07.java b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketServerHandshaker07.java index 514dd1a12b..e7b76de3a7 100644 --- a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketServerHandshaker07.java +++ b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketServerHandshaker07.java @@ -15,8 +15,8 @@ */ package io.netty.handler.codec.http.websocketx; -import io.netty.channel.ChannelInboundByteHandler; -import io.netty.channel.ChannelOutboundMessageHandler; +import io.netty.channel.ChannelInboundHandler; +import io.netty.channel.ChannelOutboundHandler; import io.netty.handler.codec.http.DefaultFullHttpResponse; import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.FullHttpResponse; @@ -132,12 +132,12 @@ public class WebSocketServerHandshaker07 extends WebSocketServerHandshaker { } @Override - protected ChannelInboundByteHandler newWebsocketDecoder() { + protected ChannelInboundHandler newWebsocketDecoder() { return new WebSocket07FrameDecoder(true, allowExtensions, maxFramePayloadLength()); } @Override - protected ChannelOutboundMessageHandler newWebSocketEncoder() { + protected ChannelOutboundHandler newWebSocketEncoder() { return new WebSocket07FrameEncoder(false); } } diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketServerHandshaker08.java b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketServerHandshaker08.java index d465b81f18..98bc9dd800 100644 --- a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketServerHandshaker08.java +++ b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketServerHandshaker08.java @@ -15,8 +15,8 @@ */ package io.netty.handler.codec.http.websocketx; -import io.netty.channel.ChannelInboundByteHandler; -import io.netty.channel.ChannelOutboundMessageHandler; +import io.netty.channel.ChannelInboundHandler; +import io.netty.channel.ChannelOutboundHandler; import io.netty.handler.codec.http.DefaultFullHttpResponse; import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.FullHttpResponse; @@ -131,12 +131,12 @@ public class WebSocketServerHandshaker08 extends WebSocketServerHandshaker { } @Override - protected ChannelInboundByteHandler newWebsocketDecoder() { + protected ChannelInboundHandler newWebsocketDecoder() { return new WebSocket08FrameDecoder(true, allowExtensions, maxFramePayloadLength()); } @Override - protected ChannelOutboundMessageHandler newWebSocketEncoder() { + protected ChannelOutboundHandler newWebSocketEncoder() { return new WebSocket08FrameEncoder(false); } } diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketServerHandshaker13.java b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketServerHandshaker13.java index 470fb86dd9..611294adde 100644 --- a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketServerHandshaker13.java +++ b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketServerHandshaker13.java @@ -15,8 +15,8 @@ */ package io.netty.handler.codec.http.websocketx; -import io.netty.channel.ChannelInboundByteHandler; -import io.netty.channel.ChannelOutboundMessageHandler; +import io.netty.channel.ChannelInboundHandler; +import io.netty.channel.ChannelOutboundHandler; import io.netty.handler.codec.http.DefaultFullHttpResponse; import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.FullHttpResponse; @@ -130,12 +130,12 @@ public class WebSocketServerHandshaker13 extends WebSocketServerHandshaker { } @Override - protected ChannelInboundByteHandler newWebsocketDecoder() { + protected ChannelInboundHandler newWebsocketDecoder() { return new WebSocket13FrameDecoder(true, allowExtensions, maxFramePayloadLength()); } @Override - protected ChannelOutboundMessageHandler newWebSocketEncoder() { + protected ChannelOutboundHandler newWebSocketEncoder() { return new WebSocket13FrameEncoder(false); } } diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketServerProtocolHandler.java b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketServerProtocolHandler.java index aad5f9be07..449444cc37 100644 --- a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketServerProtocolHandler.java +++ b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketServerProtocolHandler.java @@ -19,9 +19,10 @@ import io.netty.buffer.Unpooled; import io.netty.channel.ChannelFutureListener; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.ChannelInboundMessageHandlerAdapter; -import io.netty.channel.ChannelStateHandler; +import io.netty.channel.ChannelInboundHandler; +import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.channel.ChannelPipeline; +import io.netty.channel.MessageList; import io.netty.handler.codec.http.DefaultFullHttpResponse; import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.FullHttpResponse; @@ -43,7 +44,7 @@ import static io.netty.handler.codec.http.HttpVersion.*; * to the io.netty.example.http.websocketx.server.WebSocketServer example. * * To know once a handshake was done you can intercept the - * {@link ChannelStateHandler#userEventTriggered(ChannelHandlerContext, Object)} and check if the event was of type + * {@link ChannelInboundHandler#userEventTriggered(ChannelHandlerContext, Object)} and check if the event was of type * {@link ServerHandshakeStateEvent#HANDSHAKE_COMPLETE}. */ public class WebSocketServerProtocolHandler extends WebSocketProtocolHandler { @@ -90,14 +91,14 @@ public class WebSocketServerProtocolHandler extends WebSocketProtocolHandler { } @Override - public void messageReceived(ChannelHandlerContext ctx, WebSocketFrame frame) throws Exception { + protected void decode(ChannelHandlerContext ctx, WebSocketFrame frame, MessageList out) throws Exception { if (frame instanceof CloseWebSocketFrame) { WebSocketServerHandshaker handshaker = getHandshaker(ctx); frame.retain(); handshaker.close(ctx.channel(), (CloseWebSocketFrame) frame); return; } - super.messageReceived(ctx, frame); + super.decode(ctx, frame, out); } @Override @@ -120,12 +121,19 @@ public class WebSocketServerProtocolHandler extends WebSocketProtocolHandler { } static ChannelHandler forbiddenHttpRequestResponder() { - return new ChannelInboundMessageHandlerAdapter() { + return new ChannelInboundHandlerAdapter() { @Override - public void messageReceived(ChannelHandlerContext ctx, FullHttpRequest msg) throws Exception { - FullHttpResponse response = - new DefaultFullHttpResponse(HTTP_1_1, HttpResponseStatus.FORBIDDEN); - ctx.channel().write(response); + public void messageReceived(final ChannelHandlerContext ctx, MessageList msgs) throws Exception { + for (int i = 0; i < msgs.size(); i++) { + Object msg = msgs.get(i); + if (msg instanceof FullHttpRequest) { + FullHttpResponse response = + new DefaultFullHttpResponse(HTTP_1_1, HttpResponseStatus.FORBIDDEN); + ctx.channel().write(response); + msgs.remove(i--); + } + } + ctx.fireMessageReceived(msgs); } }; } diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketServerProtocolHandshakeHandler.java b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketServerProtocolHandshakeHandler.java index c30fff92e4..31e4ada4ee 100644 --- a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketServerProtocolHandshakeHandler.java +++ b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketServerProtocolHandshakeHandler.java @@ -18,8 +18,9 @@ package io.netty.handler.codec.http.websocketx; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelFutureListener; import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.ChannelInboundMessageHandlerAdapter; +import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.channel.ChannelPipeline; +import io.netty.channel.MessageList; import io.netty.handler.codec.http.DefaultFullHttpResponse; import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.HttpHeaders; @@ -36,7 +37,7 @@ import static io.netty.handler.codec.http.HttpVersion.*; * Handles the HTTP handshake (the HTTP Upgrade request) for {@link WebSocketServerProtocolHandler}. */ class WebSocketServerProtocolHandshakeHandler - extends ChannelInboundMessageHandlerAdapter { + extends ChannelInboundHandlerAdapter { private final String websocketPath; private final String subprotocols; @@ -50,33 +51,37 @@ class WebSocketServerProtocolHandshakeHandler } @Override - public void messageReceived(final ChannelHandlerContext ctx, FullHttpRequest req) throws Exception { - if (req.getMethod() != GET) { - sendHttpResponse(ctx, req, new DefaultFullHttpResponse(HTTP_1_1, FORBIDDEN)); - return; - } + public void messageReceived(final ChannelHandlerContext ctx, MessageList msgs) throws Exception { + MessageList requests = msgs.cast(); + for (int i = 0; i < requests.size(); i++) { + FullHttpRequest req = requests.get(i); + if (req.getMethod() != GET) { + sendHttpResponse(ctx, req, new DefaultFullHttpResponse(HTTP_1_1, FORBIDDEN)); + return; + } - final WebSocketServerHandshakerFactory wsFactory = new WebSocketServerHandshakerFactory( - getWebSocketLocation(ctx.pipeline(), req, websocketPath), subprotocols, allowExtensions); - final WebSocketServerHandshaker handshaker = wsFactory.newHandshaker(req); - if (handshaker == null) { - WebSocketServerHandshakerFactory.sendUnsupportedWebSocketVersionResponse(ctx.channel()); - } else { - final ChannelFuture handshakeFuture = handshaker.handshake(ctx.channel(), req); - handshakeFuture.addListener(new ChannelFutureListener() { - @Override - public void operationComplete(ChannelFuture future) throws Exception { - if (!future.isSuccess()) { - ctx.fireExceptionCaught(future.cause()); - } else { - ctx.fireUserEventTriggered( - WebSocketServerProtocolHandler.ServerHandshakeStateEvent.HANDSHAKE_COMPLETE); + final WebSocketServerHandshakerFactory wsFactory = new WebSocketServerHandshakerFactory( + getWebSocketLocation(ctx.pipeline(), req, websocketPath), subprotocols, allowExtensions); + final WebSocketServerHandshaker handshaker = wsFactory.newHandshaker(req); + if (handshaker == null) { + WebSocketServerHandshakerFactory.sendUnsupportedWebSocketVersionResponse(ctx.channel()); + } else { + final ChannelFuture handshakeFuture = handshaker.handshake(ctx.channel(), req); + handshakeFuture.addListener(new ChannelFutureListener() { + @Override + public void operationComplete(ChannelFuture future) throws Exception { + if (!future.isSuccess()) { + ctx.fireExceptionCaught(future.cause()); + } else { + ctx.fireUserEventTriggered( + WebSocketServerProtocolHandler.ServerHandshakeStateEvent.HANDSHAKE_COMPLETE); + } } - } - }); - WebSocketServerProtocolHandler.setHandshaker(ctx, handshaker); - ctx.pipeline().replace(this, "WS403Responder", - WebSocketServerProtocolHandler.forbiddenHttpRequestResponder()); + }); + WebSocketServerProtocolHandler.setHandshaker(ctx, handshaker); + ctx.pipeline().replace(this, "WS403Responder", + WebSocketServerProtocolHandler.forbiddenHttpRequestResponder()); + } } } diff --git a/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyFrameCodec.java b/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyFrameCodec.java index 67b73b1fad..d18952f6fb 100644 --- a/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyFrameCodec.java +++ b/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyFrameCodec.java @@ -15,20 +15,12 @@ */ package io.netty.handler.codec.spdy; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.MessageBuf; -import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.ChannelInboundByteHandler; -import io.netty.channel.ChannelOutboundMessageHandler; import io.netty.channel.CombinedChannelDuplexHandler; - /** * A combination of {@link SpdyFrameDecoder} and {@link SpdyFrameEncoder}. */ -public final class SpdyFrameCodec - extends CombinedChannelDuplexHandler - implements ChannelInboundByteHandler, ChannelOutboundMessageHandler { +public final class SpdyFrameCodec extends CombinedChannelDuplexHandler { /** * Creates a new instance with the specified {@code version} and @@ -51,27 +43,4 @@ public final class SpdyFrameCodec new SpdyFrameDecoder(version, maxChunkSize, maxHeaderSize), new SpdyFrameEncoder(version, compressionLevel, windowBits, memLevel)); } - - private SpdyFrameDecoder decoder() { - return (SpdyFrameDecoder) stateHandler(); - } - - private SpdyFrameEncoder encoder() { - return (SpdyFrameEncoder) operationHandler(); - } - - @Override - public ByteBuf newInboundBuffer(ChannelHandlerContext ctx) throws Exception { - return decoder().newInboundBuffer(ctx); - } - - @Override - public void discardInboundReadBytes(ChannelHandlerContext ctx) throws Exception { - decoder().discardInboundReadBytes(ctx); - } - - @Override - public MessageBuf newOutboundBuffer(ChannelHandlerContext ctx) throws Exception { - return encoder().newOutboundBuffer(ctx); - } } diff --git a/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyFrameDecoder.java b/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyFrameDecoder.java index 6a0de974d1..4147f5ac5d 100644 --- a/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyFrameDecoder.java +++ b/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyFrameDecoder.java @@ -16,9 +16,9 @@ package io.netty.handler.codec.spdy; import io.netty.buffer.ByteBuf; -import io.netty.buffer.MessageBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.MessageList; import io.netty.handler.codec.ByteToMessageDecoder; import io.netty.handler.codec.TooLongFrameException; @@ -94,7 +94,7 @@ public class SpdyFrameDecoder extends ByteToMessageDecoder { } @Override - public void decodeLast(ChannelHandlerContext ctx, ByteBuf in, MessageBuf out) throws Exception { + public void decodeLast(ChannelHandlerContext ctx, ByteBuf in, MessageList out) throws Exception { try { decode(ctx, in, out); } finally { @@ -103,7 +103,7 @@ public class SpdyFrameDecoder extends ByteToMessageDecoder { } @Override - protected void decode(ChannelHandlerContext ctx, ByteBuf buffer, MessageBuf out) throws Exception { + protected void decode(ChannelHandlerContext ctx, ByteBuf buffer, MessageList out) throws Exception { switch(state) { case READ_COMMON_HEADER: state = readCommonHeader(buffer); diff --git a/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyHttpCodec.java b/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyHttpCodec.java index cfb73bf528..562aef5b1c 100644 --- a/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyHttpCodec.java +++ b/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyHttpCodec.java @@ -15,20 +15,13 @@ */ package io.netty.handler.codec.spdy; -import io.netty.buffer.MessageBuf; -import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.ChannelInboundMessageHandler; -import io.netty.channel.ChannelOutboundMessageHandler; import io.netty.channel.CombinedChannelDuplexHandler; -import io.netty.handler.codec.http.HttpObject; - /** * A combination of {@link SpdyHttpDecoder} and {@link SpdyHttpEncoder} */ public final class SpdyHttpCodec - extends CombinedChannelDuplexHandler - implements ChannelInboundMessageHandler, ChannelOutboundMessageHandler { + extends CombinedChannelDuplexHandler { /** * Creates a new instance with the specified decoder options. @@ -36,22 +29,4 @@ public final class SpdyHttpCodec public SpdyHttpCodec(int version, int maxContentLength) { super(new SpdyHttpDecoder(version, maxContentLength), new SpdyHttpEncoder(version)); } - - private SpdyHttpDecoder decoder() { - return (SpdyHttpDecoder) stateHandler(); - } - - private SpdyHttpEncoder encoder() { - return (SpdyHttpEncoder) operationHandler(); - } - - @Override - public MessageBuf newInboundBuffer(ChannelHandlerContext ctx) throws Exception { - return decoder().newInboundBuffer(ctx); - } - - @Override - public MessageBuf newOutboundBuffer(ChannelHandlerContext ctx) throws Exception { - return encoder().newOutboundBuffer(ctx); - } } diff --git a/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyHttpDecoder.java b/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyHttpDecoder.java index ee0874f16a..e10fc2809c 100644 --- a/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyHttpDecoder.java +++ b/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyHttpDecoder.java @@ -16,8 +16,8 @@ package io.netty.handler.codec.spdy; import io.netty.buffer.ByteBuf; -import io.netty.buffer.MessageBuf; import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.MessageList; import io.netty.handler.codec.MessageToMessageDecoder; import io.netty.handler.codec.TooLongFrameException; import io.netty.handler.codec.http.DefaultFullHttpRequest; @@ -91,7 +91,7 @@ public class SpdyHttpDecoder extends MessageToMessageDecoder out) + protected void decode(ChannelHandlerContext ctx, SpdyDataOrControlFrame msg, MessageList out) throws Exception { if (msg instanceof SpdySynStreamFrame) { diff --git a/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyHttpEncoder.java b/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyHttpEncoder.java index 7400a08227..136f7bb996 100644 --- a/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyHttpEncoder.java +++ b/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyHttpEncoder.java @@ -15,8 +15,8 @@ */ package io.netty.handler.codec.spdy; -import io.netty.buffer.MessageBuf; import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.MessageList; import io.netty.handler.codec.MessageToMessageEncoder; import io.netty.handler.codec.UnsupportedMessageTypeException; import io.netty.handler.codec.http.FullHttpRequest; @@ -139,7 +139,7 @@ public class SpdyHttpEncoder extends MessageToMessageEncoder { } @Override - protected void encode(ChannelHandlerContext ctx, HttpObject msg, MessageBuf out) throws Exception { + protected void encode(ChannelHandlerContext ctx, HttpObject msg, MessageList out) throws Exception { boolean valid = false; diff --git a/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyHttpResponseStreamIdHandler.java b/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyHttpResponseStreamIdHandler.java index cb18684d67..b30d848465 100644 --- a/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyHttpResponseStreamIdHandler.java +++ b/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyHttpResponseStreamIdHandler.java @@ -15,9 +15,9 @@ */ package io.netty.handler.codec.spdy; -import io.netty.buffer.BufUtil; -import io.netty.buffer.MessageBuf; +import io.netty.buffer.ByteBufUtil; import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.MessageList; import io.netty.handler.codec.MessageToMessageCodec; import io.netty.handler.codec.http.HttpMessage; @@ -40,17 +40,17 @@ public class SpdyHttpResponseStreamIdHandler extends } @Override - protected void encode(ChannelHandlerContext ctx, HttpMessage msg, MessageBuf out) throws Exception { + protected void encode(ChannelHandlerContext ctx, HttpMessage msg, MessageList out) throws Exception { Integer id = ids.poll(); if (id != null && id.intValue() != NO_ID && !msg.headers().contains(SpdyHttpHeaders.Names.STREAM_ID)) { SpdyHttpHeaders.setStreamId(msg, id); } - out.add(BufUtil.retain(msg)); + out.add(ByteBufUtil.retain(msg)); } @Override - protected void decode(ChannelHandlerContext ctx, Object msg, MessageBuf out) throws Exception { + protected void decode(ChannelHandlerContext ctx, Object msg, MessageList out) throws Exception { if (msg instanceof HttpMessage) { boolean contains = ((HttpMessage) msg).headers().contains(SpdyHttpHeaders.Names.STREAM_ID); if (!contains) { @@ -62,6 +62,6 @@ public class SpdyHttpResponseStreamIdHandler extends ids.remove(((SpdyRstStreamFrame) msg).getStreamId()); } - out.add(BufUtil.retain(msg)); + out.add(ByteBufUtil.retain(msg)); } } diff --git a/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyOrHttpChooser.java b/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyOrHttpChooser.java index 9baca054eb..b14fec68ff 100644 --- a/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyOrHttpChooser.java +++ b/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyOrHttpChooser.java @@ -15,14 +15,12 @@ */ package io.netty.handler.codec.spdy; -import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.ChannelHandlerUtil; -import io.netty.channel.ChannelInboundByteHandler; -import io.netty.channel.ChannelInboundByteHandlerAdapter; -import io.netty.channel.ChannelInboundMessageHandler; +import io.netty.channel.ChannelInboundHandler; +import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.channel.ChannelPipeline; +import io.netty.channel.MessageList; import io.netty.handler.codec.http.HttpObjectAggregator; import io.netty.handler.codec.http.HttpRequestDecoder; import io.netty.handler.codec.http.HttpResponseEncoder; @@ -31,11 +29,11 @@ import io.netty.handler.ssl.SslHandler; import javax.net.ssl.SSLEngine; /** - * {@link ChannelInboundByteHandler} which is responsible to setup the {@link ChannelPipeline} either for + * {@link ChannelInboundHandler} which is responsible to setup the {@link ChannelPipeline} either for * HTTP or SPDY. This offers an easy way for users to support both at the same time while not care to * much about the low-level details. */ -public abstract class SpdyOrHttpChooser extends ChannelInboundByteHandlerAdapter { +public abstract class SpdyOrHttpChooser extends ChannelInboundHandlerAdapter { // TODO: Replace with generic NPN handler @@ -63,25 +61,13 @@ public abstract class SpdyOrHttpChooser extends ChannelInboundByteHandlerAdapter protected abstract SelectedProtocol getProtocol(SSLEngine engine); @Override - public ByteBuf newInboundBuffer(ChannelHandlerContext ctx) throws Exception { - return ChannelHandlerUtil.allocate(ctx); - } - - @Override - public void discardInboundReadBytes(ChannelHandlerContext ctx) throws Exception { - // No need to discard anything because this handler will be replaced with something else very quickly. - } - - @Override - public void inboundBufferUpdated(ChannelHandlerContext ctx, ByteBuf in) throws Exception { + public void messageReceived(ChannelHandlerContext ctx, MessageList in) throws Exception { if (initPipeline(ctx)) { - ctx.nextInboundByteBuffer().writeBytes(in); - // When we reached here we can remove this handler as its now clear what protocol we want to use // from this point on. ctx.pipeline().remove(this); - ctx.fireInboundBufferUpdated(); + ctx.fireMessageReceived(in); } } @@ -140,21 +126,21 @@ public abstract class SpdyOrHttpChooser extends ChannelInboundByteHandlerAdapter } /** - * Create the {@link ChannelInboundMessageHandler} that is responsible for handling the http requests + * Create the {@link ChannelInboundHandler} that is responsible for handling the http requests * when the {@link SelectedProtocol} was {@link SelectedProtocol#HTTP_1_0} or * {@link SelectedProtocol#HTTP_1_1} */ - protected abstract ChannelInboundMessageHandler> createHttpRequestHandlerForHttp(); + protected abstract ChannelInboundHandler createHttpRequestHandlerForHttp(); /** - * Create the {@link ChannelInboundMessageHandler} that is responsible for handling the http responses + * Create the {@link ChannelInboundHandler} that is responsible for handling the http responses * when the {@link SelectedProtocol} was {@link SelectedProtocol#SPDY_2} or * {@link SelectedProtocol#SPDY_3}. * * Bye default this getMethod will just delecate to {@link #createHttpRequestHandlerForHttp()}, but * sub-classes may override this to change the behaviour. */ - protected ChannelInboundMessageHandler> createHttpRequestHandlerForSpdy() { + protected ChannelInboundHandler createHttpRequestHandlerForSpdy() { return createHttpRequestHandlerForHttp(); } } diff --git a/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdySessionHandler.java b/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdySessionHandler.java index 696a1d88b9..fce1fb7b80 100644 --- a/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdySessionHandler.java +++ b/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdySessionHandler.java @@ -15,15 +15,12 @@ */ package io.netty.handler.codec.spdy; -import io.netty.buffer.MessageBuf; -import io.netty.buffer.Unpooled; import io.netty.channel.ChannelDuplexHandler; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelFutureListener; import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.ChannelInboundMessageHandler; -import io.netty.channel.ChannelOutboundMessageHandler; import io.netty.channel.ChannelPromise; +import io.netty.channel.MessageList; import io.netty.util.internal.EmptyArrays; import java.util.concurrent.atomic.AtomicInteger; @@ -32,8 +29,7 @@ import java.util.concurrent.atomic.AtomicInteger; * Manages streams within a SPDY session. */ public class SpdySessionHandler - extends ChannelDuplexHandler - implements ChannelInboundMessageHandler, ChannelOutboundMessageHandler { + extends ChannelDuplexHandler { private static final SpdyProtocolException PROTOCOL_EXCEPTION = new SpdyProtocolException(); private static final SpdyProtocolException STREAM_CLOSED = new SpdyProtocolException("Stream closed"); @@ -85,21 +81,11 @@ public class SpdySessionHandler } @Override - public MessageBuf newInboundBuffer(ChannelHandlerContext ctx) throws Exception { - return Unpooled.messageBuffer(); - } - - @Override - public MessageBuf newOutboundBuffer(ChannelHandlerContext ctx) throws Exception { - return Unpooled.messageBuffer(); - } - - @Override - public void inboundBufferUpdated(ChannelHandlerContext ctx) throws Exception { - MessageBuf in = ctx.inboundMessageBuffer(); + public void messageReceived(ChannelHandlerContext ctx, MessageList in) throws Exception { boolean handled = false; - for (;;) { - Object msg = in.poll(); + MessageList out = MessageList.newInstance(); + for (int i = 0 ; i < in.size(); i++) { + Object msg = in.get(i); if (msg == null) { break; } @@ -108,18 +94,20 @@ public class SpdySessionHandler // Let the next handlers handle the buffered messages before SYN_STREAM message updates the // lastGoodStreamId. if (handled) { - ctx.fireInboundBufferUpdated(); + ctx.fireMessageReceived(out); + out = MessageList.newInstance(); } } - handleInboundMessage(ctx, msg); + handleInboundMessage(ctx, msg, out); handled = true; } - ctx.fireInboundBufferUpdated(); + in.recycle(); + ctx.fireMessageReceived(out); } - private void handleInboundMessage(ChannelHandlerContext ctx, Object msg) throws Exception { + private void handleInboundMessage(ChannelHandlerContext ctx, Object msg, MessageList out) throws Exception { if (msg instanceof SpdyDataFrame) { @@ -152,22 +140,22 @@ public class SpdySessionHandler // Check if we received a data frame for a Stream-ID which is not open if (!spdySession.isActiveStream(streamID)) { if (streamID <= lastGoodStreamId) { - issueStreamError(ctx, streamID, SpdyStreamStatus.PROTOCOL_ERROR); + issueStreamError(ctx, streamID, SpdyStreamStatus.PROTOCOL_ERROR, out); } else if (!sentGoAwayFrame) { - issueStreamError(ctx, streamID, SpdyStreamStatus.INVALID_STREAM); + issueStreamError(ctx, streamID, SpdyStreamStatus.INVALID_STREAM, out); } return; } // Check if we received a data frame for a stream which is half-closed if (spdySession.isRemoteSideClosed(streamID)) { - issueStreamError(ctx, streamID, SpdyStreamStatus.STREAM_ALREADY_CLOSED); + issueStreamError(ctx, streamID, SpdyStreamStatus.STREAM_ALREADY_CLOSED, out); return; } // Check if we received a data frame before receiving a SYN_REPLY if (!isRemoteInitiatedID(streamID) && !spdySession.hasReceivedReply(streamID)) { - issueStreamError(ctx, streamID, SpdyStreamStatus.PROTOCOL_ERROR); + issueStreamError(ctx, streamID, SpdyStreamStatus.PROTOCOL_ERROR, out); return; } @@ -188,7 +176,7 @@ public class SpdySessionHandler // This difference is stored for the session when writing the SETTINGS frame // and is cleared once we send a WINDOW_UPDATE frame. if (newWindowSize < spdySession.getReceiveWindowSizeLowerBound(streamID)) { - issueStreamError(ctx, streamID, SpdyStreamStatus.FLOW_CONTROL_ERROR); + issueStreamError(ctx, streamID, SpdyStreamStatus.FLOW_CONTROL_ERROR, out); return; } @@ -198,8 +186,7 @@ public class SpdySessionHandler while (spdyDataFrame.content().readableBytes() > initialReceiveWindowSize) { SpdyDataFrame partialDataFrame = new DefaultSpdyDataFrame(streamID, spdyDataFrame.content().readSlice(initialReceiveWindowSize).retain()); - ctx.nextOutboundMessageBuffer().add(partialDataFrame); - ctx.flush(); + ctx.write(partialDataFrame); } } @@ -241,7 +228,7 @@ public class SpdySessionHandler if (spdySynStreamFrame.isInvalid() || !isRemoteInitiatedID(streamID) || spdySession.isActiveStream(streamID)) { - issueStreamError(ctx, streamID, SpdyStreamStatus.PROTOCOL_ERROR); + issueStreamError(ctx, streamID, SpdyStreamStatus.PROTOCOL_ERROR, out); return; } @@ -256,7 +243,7 @@ public class SpdySessionHandler boolean remoteSideClosed = spdySynStreamFrame.isLast(); boolean localSideClosed = spdySynStreamFrame.isUnidirectional(); if (!acceptStream(streamID, priority, remoteSideClosed, localSideClosed)) { - issueStreamError(ctx, streamID, SpdyStreamStatus.REFUSED_STREAM); + issueStreamError(ctx, streamID, SpdyStreamStatus.REFUSED_STREAM, out); return; } @@ -276,13 +263,13 @@ public class SpdySessionHandler if (spdySynReplyFrame.isInvalid() || isRemoteInitiatedID(streamID) || spdySession.isRemoteSideClosed(streamID)) { - issueStreamError(ctx, streamID, SpdyStreamStatus.INVALID_STREAM); + issueStreamError(ctx, streamID, SpdyStreamStatus.INVALID_STREAM, out); return; } // Check if we have received multiple frames for the same Stream-ID if (spdySession.hasReceivedReply(streamID)) { - issueStreamError(ctx, streamID, SpdyStreamStatus.STREAM_IN_USE); + issueStreamError(ctx, streamID, SpdyStreamStatus.STREAM_IN_USE, out); return; } @@ -368,12 +355,12 @@ public class SpdySessionHandler // Check if we received a valid HEADERS frame if (spdyHeadersFrame.isInvalid()) { - issueStreamError(ctx, streamID, SpdyStreamStatus.PROTOCOL_ERROR); + issueStreamError(ctx, streamID, SpdyStreamStatus.PROTOCOL_ERROR, out); return; } if (spdySession.isRemoteSideClosed(streamID)) { - issueStreamError(ctx, streamID, SpdyStreamStatus.INVALID_STREAM); + issueStreamError(ctx, streamID, SpdyStreamStatus.INVALID_STREAM, out); return; } @@ -406,15 +393,15 @@ public class SpdySessionHandler // Check for numerical overflow if (spdySession.getSendWindowSize(streamID) > Integer.MAX_VALUE - deltaWindowSize) { - issueStreamError(ctx, streamID, SpdyStreamStatus.FLOW_CONTROL_ERROR); + issueStreamError(ctx, streamID, SpdyStreamStatus.FLOW_CONTROL_ERROR, out); return; } - updateSendWindowSize(ctx, streamID, deltaWindowSize); + updateSendWindowSize(streamID, deltaWindowSize, out); } } - ctx.nextInboundMessageBuffer().add(msg); + out.add(msg); } @Override @@ -432,10 +419,10 @@ public class SpdySessionHandler } @Override - public void flush(ChannelHandlerContext ctx, ChannelPromise promise) throws Exception { - MessageBuf in = ctx.outboundMessageBuffer(); - for (;;) { - Object msg = in.poll(); + public void write(ChannelHandlerContext ctx, MessageList msgs, ChannelPromise promise) throws Exception { + MessageList out = MessageList.newInstance(); + for (int i = 0; i < msgs.size(); i++) { + Object msg = msgs.get(i); if (msg == null) { break; } @@ -449,24 +436,26 @@ public class SpdySessionHandler msg instanceof SpdyHeadersFrame || msg instanceof SpdyWindowUpdateFrame) { try { - handleOutboundMessage(ctx, msg); + handleOutboundMessage(ctx, msg, out); } catch (SpdyProtocolException e) { if (e == PROTOCOL_EXCEPTION) { - // on the case of PROTOCOL_EXCEPTION faile the promise directly + // on the case of PROTOCOL_EXCEPTION, fail the promise directly // See #1211 promise.setFailure(PROTOCOL_EXCEPTION); return; } } } else { - ctx.nextOutboundMessageBuffer().add(msg); + out.add(msg); } } - ctx.flush(promise); + + msgs.recycle(); + ctx.write(out, promise); } - private void handleOutboundMessage(ChannelHandlerContext ctx, Object msg) throws Exception { - + private void handleOutboundMessage(ChannelHandlerContext ctx, Object msg, MessageList out) + throws Exception { if (msg instanceof SpdyDataFrame) { SpdyDataFrame spdyDataFrame = (SpdyDataFrame) msg; @@ -656,7 +645,7 @@ public class SpdySessionHandler throw PROTOCOL_EXCEPTION; } - ctx.nextOutboundMessageBuffer().add(msg); + out.add(msg); } /* @@ -671,8 +660,7 @@ public class SpdySessionHandler private void issueSessionError( ChannelHandlerContext ctx, SpdySessionStatus status) { - sendGoAwayFrame(ctx, status); - ctx.flush().addListener(ChannelFutureListener.CLOSE); + sendGoAwayFrame(ctx, status).addListener(ChannelFutureListener.CLOSE); } /* @@ -687,7 +675,7 @@ public class SpdySessionHandler * Note: this is only called by the worker thread */ private void issueStreamError( - ChannelHandlerContext ctx, int streamID, SpdyStreamStatus status) { + ChannelHandlerContext ctx, int streamID, SpdyStreamStatus status, MessageList in) { boolean fireMessageReceived = !spdySession.isRemoteSideClosed(streamID); removeStream(ctx, streamID); @@ -695,8 +683,11 @@ public class SpdySessionHandler SpdyRstStreamFrame spdyRstStreamFrame = new DefaultSpdyRstStreamFrame(streamID, status); ctx.write(spdyRstStreamFrame); if (fireMessageReceived) { - ctx.nextInboundMessageBuffer().add(spdyRstStreamFrame); - ctx.fireInboundBufferUpdated(); + in.add(spdyRstStreamFrame); + ctx.fireMessageReceived(in); + while (!in.isEmpty()) { + in.remove(0); + } } } @@ -793,7 +784,7 @@ public class SpdySessionHandler } } - private void updateSendWindowSize(ChannelHandlerContext ctx, final int streamID, int deltaWindowSize) { + private void updateSendWindowSize(final int streamID, int deltaWindowSize, MessageList out) { synchronized (flowControlLock) { int newWindowSize = spdySession.updateSendWindowSize(streamID, deltaWindowSize); @@ -832,7 +823,7 @@ public class SpdySessionHandler halfCloseStream(streamID, false); } - ctx.nextOutboundMessageBuffer().add(spdyDataFrame); + out.add(spdyDataFrame); } else { // We can send a partial frame spdySession.updateSendWindowSize(streamID, -1 * newWindowSize); @@ -858,7 +849,7 @@ public class SpdySessionHandler // } //}); - ctx.nextOutboundMessageBuffer().add(partialDataFrame); + out.add(partialDataFrame); newWindowSize = 0; } @@ -873,8 +864,7 @@ public class SpdySessionHandler return; } - sendGoAwayFrame(ctx, SpdySessionStatus.OK); - ChannelFuture f = ctx.flush(); + ChannelFuture f = sendGoAwayFrame(ctx, SpdySessionStatus.OK); if (spdySession.noActiveStreams()) { f.addListener(new ClosingChannelFutureListener(ctx, future)); } else { @@ -884,12 +874,14 @@ public class SpdySessionHandler // FIXME: Close the connection forcibly after timeout. } - private synchronized void sendGoAwayFrame( + private synchronized ChannelFuture sendGoAwayFrame( ChannelHandlerContext ctx, SpdySessionStatus status) { if (!sentGoAwayFrame) { sentGoAwayFrame = true; SpdyGoAwayFrame spdyGoAwayFrame = new DefaultSpdyGoAwayFrame(lastGoodStreamId, status); - ctx.nextOutboundMessageBuffer().add(spdyGoAwayFrame); + return ctx.write(spdyGoAwayFrame); + } else { + return ctx.newSucceededFuture(); } } diff --git a/codec-http/src/test/java/io/netty/handler/codec/http/HttpClientCodecTest.java b/codec-http/src/test/java/io/netty/handler/codec/http/HttpClientCodecTest.java index 5ba19f180b..07af776a60 100644 --- a/codec-http/src/test/java/io/netty/handler/codec/http/HttpClientCodecTest.java +++ b/codec-http/src/test/java/io/netty/handler/codec/http/HttpClientCodecTest.java @@ -16,7 +16,7 @@ package io.netty.handler.codec.http; import io.netty.buffer.Unpooled; -import io.netty.channel.embedded.EmbeddedByteChannel; +import io.netty.channel.embedded.EmbeddedChannel; import io.netty.handler.codec.CodecException; import io.netty.handler.codec.PrematureChannelClosureException; import io.netty.util.CharsetUtil; @@ -37,7 +37,7 @@ public class HttpClientCodecTest { @Test public void testFailsNotOnRequestResponse() { HttpClientCodec codec = new HttpClientCodec(4096, 8192, 8192, true); - EmbeddedByteChannel ch = new EmbeddedByteChannel(codec); + EmbeddedChannel ch = new EmbeddedChannel(codec); ch.writeOutbound(new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, "http://localhost/")); ch.writeInbound(Unpooled.copiedBuffer(RESPONSE, CharsetUtil.ISO_8859_1)); @@ -47,7 +47,7 @@ public class HttpClientCodecTest { @Test public void testFailsNotOnRequestResponseChunked() { HttpClientCodec codec = new HttpClientCodec(4096, 8192, 8192, true); - EmbeddedByteChannel ch = new EmbeddedByteChannel(codec); + EmbeddedChannel ch = new EmbeddedChannel(codec); ch.writeOutbound(new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, "http://localhost/")); ch.writeInbound(Unpooled.copiedBuffer(CHUNKED_RESPONSE, CharsetUtil.ISO_8859_1)); @@ -57,7 +57,7 @@ public class HttpClientCodecTest { @Test public void testFailsOnMissingResponse() { HttpClientCodec codec = new HttpClientCodec(4096, 8192, 8192, true); - EmbeddedByteChannel ch = new EmbeddedByteChannel(codec); + EmbeddedChannel ch = new EmbeddedChannel(codec); assertTrue(ch.writeOutbound(new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, "http://localhost/"))); @@ -74,7 +74,7 @@ public class HttpClientCodecTest { @Test public void testFailsOnIncompleteChunkedResponse() { HttpClientCodec codec = new HttpClientCodec(4096, 8192, 8192, true); - EmbeddedByteChannel ch = new EmbeddedByteChannel(codec); + EmbeddedChannel ch = new EmbeddedChannel(codec); ch.writeOutbound(new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, "http://localhost/")); ch.writeInbound(Unpooled.copiedBuffer(INCOMPLETE_CHUNKED_RESPONSE, CharsetUtil.ISO_8859_1)); diff --git a/codec-http/src/test/java/io/netty/handler/codec/http/HttpContentCompressorTest.java b/codec-http/src/test/java/io/netty/handler/codec/http/HttpContentCompressorTest.java index b0875f9494..113b22cb52 100644 --- a/codec-http/src/test/java/io/netty/handler/codec/http/HttpContentCompressorTest.java +++ b/codec-http/src/test/java/io/netty/handler/codec/http/HttpContentCompressorTest.java @@ -15,7 +15,7 @@ */ package io.netty.handler.codec.http; -import io.netty.channel.embedded.EmbeddedMessageChannel; +import io.netty.channel.embedded.EmbeddedChannel; import io.netty.handler.codec.compression.ZlibWrapper; import io.netty.handler.codec.http.HttpHeaders.Names; import org.junit.Test; @@ -63,7 +63,7 @@ public class HttpContentCompressorTest { @Test public void testEmptyContentCompression() throws Exception { - EmbeddedMessageChannel ch = new EmbeddedMessageChannel(new HttpContentCompressor()); + EmbeddedChannel ch = new EmbeddedChannel(new HttpContentCompressor()); FullHttpRequest req = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, "/"); req.headers().set(Names.ACCEPT_ENCODING, "deflate"); ch.writeInbound(req); diff --git a/codec-http/src/test/java/io/netty/handler/codec/http/HttpContentEncoderTest.java b/codec-http/src/test/java/io/netty/handler/codec/http/HttpContentEncoderTest.java index 8e293cb412..dbf450bf25 100644 --- a/codec-http/src/test/java/io/netty/handler/codec/http/HttpContentEncoderTest.java +++ b/codec-http/src/test/java/io/netty/handler/codec/http/HttpContentEncoderTest.java @@ -19,9 +19,8 @@ package io.netty.handler.codec.http; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.embedded.EmbeddedByteChannel; -import io.netty.channel.embedded.EmbeddedMessageChannel; -import io.netty.handler.codec.ByteToByteEncoder; +import io.netty.channel.embedded.EmbeddedChannel; +import io.netty.handler.codec.MessageToByteEncoder; import io.netty.handler.codec.http.HttpHeaders.Names; import io.netty.handler.codec.http.HttpHeaders.Values; import io.netty.util.CharsetUtil; @@ -35,9 +34,9 @@ public class HttpContentEncoderTest { private static final class TestEncoder extends HttpContentEncoder { @Override protected Result beginEncode(HttpResponse headers, String acceptEncoding) { - return new Result("test", new EmbeddedByteChannel(new ByteToByteEncoder() { + return new Result("test", new EmbeddedChannel(new MessageToByteEncoder() { @Override - protected void encode(ChannelHandlerContext ctx, ByteBuf in, ByteBuf out) { + protected void encode(ChannelHandlerContext ctx, ByteBuf in, ByteBuf out) throws Exception { out.writeBytes(String.valueOf(in.readableBytes()).getBytes(CharsetUtil.US_ASCII)); in.skipBytes(in.readableBytes()); } @@ -47,7 +46,7 @@ public class HttpContentEncoderTest { @Test public void testSplitContent() throws Exception { - EmbeddedMessageChannel ch = new EmbeddedMessageChannel(new TestEncoder()); + EmbeddedChannel ch = new EmbeddedChannel(new TestEncoder()); ch.writeInbound(new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, "/")); ch.writeOutbound(new DefaultHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK)); @@ -71,7 +70,7 @@ public class HttpContentEncoderTest { @Test public void testChunkedContent() throws Exception { - EmbeddedMessageChannel ch = new EmbeddedMessageChannel(new TestEncoder()); + EmbeddedChannel ch = new EmbeddedChannel(new TestEncoder()); ch.writeInbound(new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, "/")); HttpResponse res = new DefaultHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK); @@ -98,7 +97,7 @@ public class HttpContentEncoderTest { @Test public void testFullContent() throws Exception { - EmbeddedMessageChannel ch = new EmbeddedMessageChannel(new TestEncoder()); + EmbeddedChannel ch = new EmbeddedChannel(new TestEncoder()); ch.writeInbound(new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, "/")); FullHttpResponse res = new DefaultFullHttpResponse( @@ -116,12 +115,12 @@ public class HttpContentEncoderTest { } /** - * If the length of the content is unknown, {@link HttpContentEncoder} should not skip encoding even if the - * actual length is turned out to be 0. + * If the length of the content is unknown, {@link HttpContentEncoder} should not skip encoding the content + * even if the actual length is turned out to be 0. */ @Test public void testEmptySplitContent() throws Exception { - EmbeddedMessageChannel ch = new EmbeddedMessageChannel(new TestEncoder()); + EmbeddedChannel ch = new EmbeddedChannel(new TestEncoder()); ch.writeInbound(new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, "/")); ch.writeOutbound(new DefaultHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK)); @@ -129,7 +128,7 @@ public class HttpContentEncoderTest { ch.writeOutbound(LastHttpContent.EMPTY_LAST_CONTENT); HttpContent chunk = (HttpContent) ch.readOutbound(); - assertThat(chunk.content().isReadable(), is(false)); + assertThat(chunk.content().toString(CharsetUtil.US_ASCII), is("0")); assertThat(chunk, is(instanceOf(LastHttpContent.class))); assertThat(ch.readOutbound(), is(nullValue())); } @@ -139,7 +138,7 @@ public class HttpContentEncoderTest { */ @Test public void testEmptyFullContent() throws Exception { - EmbeddedMessageChannel ch = new EmbeddedMessageChannel(new TestEncoder()); + EmbeddedChannel ch = new EmbeddedChannel(new TestEncoder()); ch.writeInbound(new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, "/")); FullHttpResponse res = new DefaultFullHttpResponse( @@ -162,7 +161,7 @@ public class HttpContentEncoderTest { assertThat(ch.readOutbound(), is(nullValue())); } - private static void assertEncodedResponse(EmbeddedMessageChannel ch) { + private static void assertEncodedResponse(EmbeddedChannel ch) { Object o = ch.readOutbound(); assertThat(o, is(instanceOf(HttpResponse.class))); diff --git a/codec-http/src/test/java/io/netty/handler/codec/http/HttpInvalidMessageTest.java b/codec-http/src/test/java/io/netty/handler/codec/http/HttpInvalidMessageTest.java index bae6eeea8a..caa5f50fe7 100644 --- a/codec-http/src/test/java/io/netty/handler/codec/http/HttpInvalidMessageTest.java +++ b/codec-http/src/test/java/io/netty/handler/codec/http/HttpInvalidMessageTest.java @@ -17,7 +17,7 @@ package io.netty.handler.codec.http; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; -import io.netty.channel.embedded.EmbeddedByteChannel; +import io.netty.channel.embedded.EmbeddedChannel; import io.netty.handler.codec.DecoderResult; import io.netty.util.CharsetUtil; import org.junit.Test; @@ -32,7 +32,7 @@ public class HttpInvalidMessageTest { @Test public void testRequestWithBadInitialLine() throws Exception { - EmbeddedByteChannel ch = new EmbeddedByteChannel(new HttpRequestDecoder()); + EmbeddedChannel ch = new EmbeddedChannel(new HttpRequestDecoder()); ch.writeInbound(Unpooled.copiedBuffer("GET / HTTP/1.0 with extra\r\n", CharsetUtil.UTF_8)); HttpRequest req = (HttpRequest) ch.readInbound(); DecoderResult dr = req.getDecoderResult(); @@ -43,7 +43,7 @@ public class HttpInvalidMessageTest { @Test public void testRequestWithBadHeader() throws Exception { - EmbeddedByteChannel ch = new EmbeddedByteChannel(new HttpRequestDecoder()); + EmbeddedChannel ch = new EmbeddedChannel(new HttpRequestDecoder()); ch.writeInbound(Unpooled.copiedBuffer("GET /maybe-something HTTP/1.0\r\n", CharsetUtil.UTF_8)); ch.writeInbound(Unpooled.copiedBuffer("Good_Name: Good Value\r\n", CharsetUtil.UTF_8)); ch.writeInbound(Unpooled.copiedBuffer("Bad=Name: Bad Value\r\n", CharsetUtil.UTF_8)); @@ -59,7 +59,7 @@ public class HttpInvalidMessageTest { @Test public void testResponseWithBadInitialLine() throws Exception { - EmbeddedByteChannel ch = new EmbeddedByteChannel(new HttpResponseDecoder()); + EmbeddedChannel ch = new EmbeddedChannel(new HttpResponseDecoder()); ch.writeInbound(Unpooled.copiedBuffer("HTTP/1.0 BAD_CODE Bad Server\r\n", CharsetUtil.UTF_8)); HttpResponse res = (HttpResponse) ch.readInbound(); DecoderResult dr = res.getDecoderResult(); @@ -70,7 +70,7 @@ public class HttpInvalidMessageTest { @Test public void testResponseWithBadHeader() throws Exception { - EmbeddedByteChannel ch = new EmbeddedByteChannel(new HttpResponseDecoder()); + EmbeddedChannel ch = new EmbeddedChannel(new HttpResponseDecoder()); ch.writeInbound(Unpooled.copiedBuffer("HTTP/1.0 200 Maybe OK\r\n", CharsetUtil.UTF_8)); ch.writeInbound(Unpooled.copiedBuffer("Good_Name: Good Value\r\n", CharsetUtil.UTF_8)); ch.writeInbound(Unpooled.copiedBuffer("Bad=Name: Bad Value\r\n", CharsetUtil.UTF_8)); @@ -86,7 +86,7 @@ public class HttpInvalidMessageTest { @Test public void testBadChunk() throws Exception { - EmbeddedByteChannel ch = new EmbeddedByteChannel(new HttpRequestDecoder()); + EmbeddedChannel ch = new EmbeddedChannel(new HttpRequestDecoder()); ch.writeInbound(Unpooled.copiedBuffer("GET / HTTP/1.0\r\n", CharsetUtil.UTF_8)); ch.writeInbound(Unpooled.copiedBuffer("Transfer-Encoding: chunked\r\n\r\n", CharsetUtil.UTF_8)); ch.writeInbound(Unpooled.copiedBuffer("BAD_LENGTH\r\n", CharsetUtil.UTF_8)); @@ -101,7 +101,7 @@ public class HttpInvalidMessageTest { ensureInboundTrafficDiscarded(ch); } - private void ensureInboundTrafficDiscarded(EmbeddedByteChannel ch) { + private void ensureInboundTrafficDiscarded(EmbeddedChannel ch) { // Generate a lot of random traffic to ensure that it's discarded silently. byte[] data = new byte[1048576]; rnd.nextBytes(data); @@ -109,9 +109,10 @@ public class HttpInvalidMessageTest { ByteBuf buf = Unpooled.wrappedBuffer(data); for (int i = 0; i < 4096; i ++) { buf.setIndex(0, data.length); - ch.writeInbound(buf); + ch.writeInbound(buf.retain()); ch.checkException(); assertNull(ch.readInbound()); } + buf.release(); } } diff --git a/codec-http/src/test/java/io/netty/handler/codec/http/HttpObjectAggregatorTest.java b/codec-http/src/test/java/io/netty/handler/codec/http/HttpObjectAggregatorTest.java index e724bc4513..d6f8fb4676 100644 --- a/codec-http/src/test/java/io/netty/handler/codec/http/HttpObjectAggregatorTest.java +++ b/codec-http/src/test/java/io/netty/handler/codec/http/HttpObjectAggregatorTest.java @@ -19,7 +19,7 @@ import io.netty.buffer.ByteBuf; import io.netty.buffer.CompositeByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.embedded.EmbeddedMessageChannel; +import io.netty.channel.embedded.EmbeddedChannel; import io.netty.handler.codec.TooLongFrameException; import io.netty.util.CharsetUtil; import org.easymock.EasyMock; @@ -34,7 +34,7 @@ public class HttpObjectAggregatorTest { @Test public void testAggregate() { HttpObjectAggregator aggr = new HttpObjectAggregator(1024 * 1024); - EmbeddedMessageChannel embedder = new EmbeddedMessageChannel(aggr); + EmbeddedChannel embedder = new EmbeddedChannel(aggr); HttpRequest message = new DefaultHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, "http://localhost"); @@ -73,7 +73,7 @@ public class HttpObjectAggregatorTest { @Test public void testAggregateWithTrailer() { HttpObjectAggregator aggr = new HttpObjectAggregator(1024 * 1024); - EmbeddedMessageChannel embedder = new EmbeddedMessageChannel(aggr); + EmbeddedChannel embedder = new EmbeddedChannel(aggr); HttpRequest message = new DefaultHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, "http://localhost"); HttpHeaders.setHeader(message, "X-Test", true); @@ -105,7 +105,7 @@ public class HttpObjectAggregatorTest { @Test public void testTooLongFrameException() { HttpObjectAggregator aggr = new HttpObjectAggregator(4); - EmbeddedMessageChannel embedder = new EmbeddedMessageChannel(aggr); + EmbeddedChannel embedder = new EmbeddedChannel(aggr); HttpRequest message = new DefaultHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, "http://localhost"); HttpContent chunk1 = new DefaultHttpContent(Unpooled.copiedBuffer("test", CharsetUtil.US_ASCII)); @@ -159,7 +159,7 @@ public class HttpObjectAggregatorTest { @Test public void testAggregateTransferEncodingChunked() { HttpObjectAggregator aggr = new HttpObjectAggregator(1024 * 1024); - EmbeddedMessageChannel embedder = new EmbeddedMessageChannel(aggr); + EmbeddedChannel embedder = new EmbeddedChannel(aggr); HttpRequest message = new DefaultHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, "http://localhost"); diff --git a/codec-http/src/test/java/io/netty/handler/codec/http/HttpServerCodecTest.java b/codec-http/src/test/java/io/netty/handler/codec/http/HttpServerCodecTest.java index 237b30fa56..68771595fc 100644 --- a/codec-http/src/test/java/io/netty/handler/codec/http/HttpServerCodecTest.java +++ b/codec-http/src/test/java/io/netty/handler/codec/http/HttpServerCodecTest.java @@ -17,7 +17,7 @@ package io.netty.handler.codec.http; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; -import io.netty.channel.embedded.EmbeddedByteChannel; +import io.netty.channel.embedded.EmbeddedChannel; import io.netty.util.CharsetUtil; import org.junit.Assert; import org.junit.Test; @@ -32,10 +32,11 @@ public class HttpServerCodecTest { int maxChunkSize = 2000; HttpServerCodec httpServerCodec = new HttpServerCodec(1000, 1000, maxChunkSize); - EmbeddedByteChannel decoderEmbedder = new EmbeddedByteChannel(httpServerCodec); + EmbeddedChannel decoderEmbedder = new EmbeddedChannel(httpServerCodec); int totalContentLength = maxChunkSize * 5; - decoderEmbedder.writeInbound(Unpooled.copiedBuffer("PUT /test HTTP/1.1\r\n" + + decoderEmbedder.writeInbound(Unpooled.copiedBuffer( + "PUT /test HTTP/1.1\r\n" + "Content-Length: " + totalContentLength + "\r\n" + "\r\n", CharsetUtil.UTF_8)); diff --git a/codec-http/src/test/java/io/netty/handler/codec/http/websocketx/WebSocketFrameAggregatorTest.java b/codec-http/src/test/java/io/netty/handler/codec/http/websocketx/WebSocketFrameAggregatorTest.java index a78ca4c102..f360329a60 100644 --- a/codec-http/src/test/java/io/netty/handler/codec/http/websocketx/WebSocketFrameAggregatorTest.java +++ b/codec-http/src/test/java/io/netty/handler/codec/http/websocketx/WebSocketFrameAggregatorTest.java @@ -17,7 +17,7 @@ package io.netty.handler.codec.http.websocketx; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; -import io.netty.channel.embedded.EmbeddedMessageChannel; +import io.netty.channel.embedded.EmbeddedChannel; import io.netty.handler.codec.TooLongFrameException; import io.netty.util.CharsetUtil; import org.junit.Assert; @@ -32,7 +32,7 @@ public class WebSocketFrameAggregatorTest { .writeBytes(content2.duplicate()).writeBytes(content3.duplicate()); @Test public void testAggregationBinary() { - EmbeddedMessageChannel channel = new EmbeddedMessageChannel(new WebSocketFrameAggregator(Integer.MAX_VALUE)); + EmbeddedChannel channel = new EmbeddedChannel(new WebSocketFrameAggregator(Integer.MAX_VALUE)); channel.writeInbound(new BinaryWebSocketFrame(true, 1, content1.copy())); channel.writeInbound(new BinaryWebSocketFrame(false, 0, content1.copy())); channel.writeInbound(new ContinuationWebSocketFrame(false, 0, content2.copy())); @@ -42,7 +42,7 @@ public class WebSocketFrameAggregatorTest { Assert.assertTrue(channel.finish()); - System.out.println(channel.lastInboundMessageBuffer().size()); + System.out.println(channel.lastInboundBuffer().size()); BinaryWebSocketFrame frame = (BinaryWebSocketFrame) channel.readInbound(); Assert.assertTrue(frame.isFinalFragment()); Assert.assertEquals(1, frame.rsv()); @@ -68,7 +68,7 @@ public class WebSocketFrameAggregatorTest { @Test public void testAggregationText() { - EmbeddedMessageChannel channel = new EmbeddedMessageChannel(new WebSocketFrameAggregator(Integer.MAX_VALUE)); + EmbeddedChannel channel = new EmbeddedChannel(new WebSocketFrameAggregator(Integer.MAX_VALUE)); channel.writeInbound(new TextWebSocketFrame(true, 1, content1.copy())); channel.writeInbound(new TextWebSocketFrame(false, 0, content1.copy())); channel.writeInbound(new ContinuationWebSocketFrame(false, 0, content2.copy())); @@ -103,7 +103,7 @@ public class WebSocketFrameAggregatorTest { @Test public void textFrameTooBig() { - EmbeddedMessageChannel channel = new EmbeddedMessageChannel(new WebSocketFrameAggregator(8)); + EmbeddedChannel channel = new EmbeddedChannel(new WebSocketFrameAggregator(8)); channel.writeInbound(new BinaryWebSocketFrame(true, 1, content1.copy())); channel.writeInbound(new BinaryWebSocketFrame(false, 0, content1.copy())); try { diff --git a/codec-http/src/test/java/io/netty/handler/codec/http/websocketx/WebSocketServerHandshaker00Test.java b/codec-http/src/test/java/io/netty/handler/codec/http/websocketx/WebSocketServerHandshaker00Test.java index 78354b607f..aa91646b92 100644 --- a/codec-http/src/test/java/io/netty/handler/codec/http/websocketx/WebSocketServerHandshaker00Test.java +++ b/codec-http/src/test/java/io/netty/handler/codec/http/websocketx/WebSocketServerHandshaker00Test.java @@ -17,7 +17,7 @@ package io.netty.handler.codec.http.websocketx; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; -import io.netty.channel.embedded.EmbeddedByteChannel; +import io.netty.channel.embedded.EmbeddedChannel; import io.netty.handler.codec.http.DefaultFullHttpRequest; import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.HttpHeaders.Names; @@ -39,7 +39,7 @@ public class WebSocketServerHandshaker00Test { @Test public void testPerformOpeningHandshake() { - EmbeddedByteChannel ch = new EmbeddedByteChannel( + EmbeddedChannel ch = new EmbeddedChannel( new HttpObjectAggregator(42), new HttpRequestDecoder(), new HttpResponseEncoder()); FullHttpRequest req = new DefaultFullHttpRequest( @@ -56,9 +56,9 @@ public class WebSocketServerHandshaker00Test { new WebSocketServerHandshaker00( "ws://example.com/chat", "chat", Integer.MAX_VALUE).handshake(ch, req); - ByteBuf resBuf = ch.readOutbound(); + ByteBuf resBuf = (ByteBuf) ch.readOutbound(); - EmbeddedByteChannel ch2 = new EmbeddedByteChannel(new HttpResponseDecoder()); + EmbeddedChannel ch2 = new EmbeddedChannel(new HttpResponseDecoder()); ch2.writeInbound(resBuf); HttpResponse res = (HttpResponse) ch2.readInbound(); diff --git a/codec-http/src/test/java/io/netty/handler/codec/http/websocketx/WebSocketServerHandshaker08Test.java b/codec-http/src/test/java/io/netty/handler/codec/http/websocketx/WebSocketServerHandshaker08Test.java index f49ac6b101..6b6d3c7aca 100644 --- a/codec-http/src/test/java/io/netty/handler/codec/http/websocketx/WebSocketServerHandshaker08Test.java +++ b/codec-http/src/test/java/io/netty/handler/codec/http/websocketx/WebSocketServerHandshaker08Test.java @@ -16,7 +16,7 @@ package io.netty.handler.codec.http.websocketx; import io.netty.buffer.ByteBuf; -import io.netty.channel.embedded.EmbeddedByteChannel; +import io.netty.channel.embedded.EmbeddedChannel; import io.netty.handler.codec.http.DefaultFullHttpRequest; import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.HttpHeaders.Names; @@ -36,7 +36,7 @@ public class WebSocketServerHandshaker08Test { @Test public void testPerformOpeningHandshake() { - EmbeddedByteChannel ch = new EmbeddedByteChannel( + EmbeddedChannel ch = new EmbeddedChannel( new HttpObjectAggregator(42), new HttpRequestDecoder(), new HttpResponseEncoder()); FullHttpRequest req = new DefaultFullHttpRequest(HTTP_1_1, HttpMethod.GET, "/chat"); @@ -51,9 +51,9 @@ public class WebSocketServerHandshaker08Test { new WebSocketServerHandshaker08( "ws://example.com/chat", "chat", false, Integer.MAX_VALUE).handshake(ch, req); - ByteBuf resBuf = ch.readOutbound(); + ByteBuf resBuf = (ByteBuf) ch.readOutbound(); - EmbeddedByteChannel ch2 = new EmbeddedByteChannel(new HttpResponseDecoder()); + EmbeddedChannel ch2 = new EmbeddedChannel(new HttpResponseDecoder()); ch2.writeInbound(resBuf); HttpResponse res = (HttpResponse) ch2.readInbound(); diff --git a/codec-http/src/test/java/io/netty/handler/codec/http/websocketx/WebSocketServerHandshaker13Test.java b/codec-http/src/test/java/io/netty/handler/codec/http/websocketx/WebSocketServerHandshaker13Test.java index 791de6a604..aacc460a26 100644 --- a/codec-http/src/test/java/io/netty/handler/codec/http/websocketx/WebSocketServerHandshaker13Test.java +++ b/codec-http/src/test/java/io/netty/handler/codec/http/websocketx/WebSocketServerHandshaker13Test.java @@ -16,7 +16,7 @@ package io.netty.handler.codec.http.websocketx; import io.netty.buffer.ByteBuf; -import io.netty.channel.embedded.EmbeddedByteChannel; +import io.netty.channel.embedded.EmbeddedChannel; import io.netty.handler.codec.http.DefaultFullHttpRequest; import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.HttpHeaders.Names; @@ -36,7 +36,7 @@ public class WebSocketServerHandshaker13Test { @Test public void testPerformOpeningHandshake() { - EmbeddedByteChannel ch = new EmbeddedByteChannel( + EmbeddedChannel ch = new EmbeddedChannel( new HttpObjectAggregator(42), new HttpRequestDecoder(), new HttpResponseEncoder()); FullHttpRequest req = new DefaultFullHttpRequest(HTTP_1_1, HttpMethod.GET, "/chat"); @@ -51,9 +51,9 @@ public class WebSocketServerHandshaker13Test { new WebSocketServerHandshaker13( "ws://example.com/chat", "chat", false, Integer.MAX_VALUE).handshake(ch, req); - ByteBuf resBuf = ch.readOutbound(); + ByteBuf resBuf = (ByteBuf) ch.readOutbound(); - EmbeddedByteChannel ch2 = new EmbeddedByteChannel(new HttpResponseDecoder()); + EmbeddedChannel ch2 = new EmbeddedChannel(new HttpResponseDecoder()); ch2.writeInbound(resBuf); HttpResponse res = (HttpResponse) ch2.readInbound(); diff --git a/codec-http/src/test/java/io/netty/handler/codec/http/websocketx/WebSocketServerProtocolHandlerTest.java b/codec-http/src/test/java/io/netty/handler/codec/http/websocketx/WebSocketServerProtocolHandlerTest.java index 643363fd16..67f635122b 100644 --- a/codec-http/src/test/java/io/netty/handler/codec/http/websocketx/WebSocketServerProtocolHandlerTest.java +++ b/codec-http/src/test/java/io/netty/handler/codec/http/websocketx/WebSocketServerProtocolHandlerTest.java @@ -15,25 +15,26 @@ */ package io.netty.handler.codec.http.websocketx; -import io.netty.buffer.MessageBuf; -import io.netty.buffer.Unpooled; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.ChannelInboundMessageHandlerAdapter; -import io.netty.channel.ChannelOperationHandlerAdapter; -import io.netty.channel.ChannelOutboundMessageHandler; +import io.netty.channel.ChannelInboundHandlerAdapter; +import io.netty.channel.ChannelOutboundHandlerAdapter; import io.netty.channel.ChannelPromise; -import io.netty.channel.embedded.EmbeddedMessageChannel; +import io.netty.channel.MessageList; +import io.netty.channel.embedded.EmbeddedChannel; import io.netty.handler.codec.http.DefaultFullHttpRequest; import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.FullHttpResponse; import io.netty.handler.codec.http.HttpMethod; import io.netty.handler.codec.http.HttpRequest; import io.netty.handler.codec.http.HttpRequestDecoder; -import io.netty.handler.codec.http.HttpResponse; import io.netty.handler.codec.http.HttpResponseEncoder; +import org.junit.Before; import org.junit.Test; +import java.util.ArrayDeque; +import java.util.Queue; + import static io.netty.handler.codec.http.HttpHeaders.Values.*; import static io.netty.handler.codec.http.HttpResponseStatus.*; import static io.netty.handler.codec.http.HttpVersion.*; @@ -41,29 +42,36 @@ import static org.junit.Assert.*; public class WebSocketServerProtocolHandlerTest { + private final Queue responses = new ArrayDeque(); + + @Before + public void setUp() { + responses.clear(); + } + @Test public void testHttpUpgradeRequest() throws Exception { - EmbeddedMessageChannel ch = createChannel(new MockOutboundHandler()); + EmbeddedChannel ch = createChannel(new MockOutboundHandler()); ChannelHandlerContext handshakerCtx = ch.pipeline().context(WebSocketServerProtocolHandshakeHandler.class); writeUpgradeRequest(ch); - assertEquals(SWITCHING_PROTOCOLS, ((HttpResponse) ch.outboundMessageBuffer().poll()).getStatus()); + assertEquals(SWITCHING_PROTOCOLS, responses.remove().getStatus()); assertNotNull(WebSocketServerProtocolHandler.getHandshaker(handshakerCtx)); } @Test public void testSubsequentHttpRequestsAfterUpgradeShouldReturn403() throws Exception { - EmbeddedMessageChannel ch = createChannel(new MockOutboundHandler()); + EmbeddedChannel ch = createChannel(); writeUpgradeRequest(ch); - assertEquals(SWITCHING_PROTOCOLS, ((HttpResponse) ch.outboundMessageBuffer().poll()).getStatus()); + assertEquals(SWITCHING_PROTOCOLS, responses.remove().getStatus()); ch.writeInbound(new DefaultFullHttpRequest(HTTP_1_1, HttpMethod.GET, "/test")); - assertEquals(FORBIDDEN, ((HttpResponse) ch.outboundMessageBuffer().poll()).getStatus()); + assertEquals(FORBIDDEN, responses.remove().getStatus()); } @Test public void testHttpUpgradeRequestInvalidUpgradeHeader() { - EmbeddedMessageChannel ch = createChannel(); + EmbeddedChannel ch = createChannel(); FullHttpRequest httpRequestWithEntity = new WebSocketRequestBuilder().httpVersion(HTTP_1_1) .method(HttpMethod.GET) .uri("/test") @@ -74,14 +82,14 @@ public class WebSocketServerProtocolHandlerTest { ch.writeInbound(httpRequestWithEntity); - FullHttpResponse response = getHttpResponse(ch); + FullHttpResponse response = responses.remove(); assertEquals(BAD_REQUEST, response.getStatus()); assertEquals("not a WebSocket handshake request: missing upgrade", getResponseMessage(response)); } @Test public void testHttpUpgradeRequestMissingWSKeyHeader() { - EmbeddedMessageChannel ch = createChannel(); + EmbeddedChannel ch = createChannel(); HttpRequest httpRequest = new WebSocketRequestBuilder().httpVersion(HTTP_1_1) .method(HttpMethod.GET) .uri("/test") @@ -93,7 +101,7 @@ public class WebSocketServerProtocolHandlerTest { ch.writeInbound(httpRequest); - FullHttpResponse response = getHttpResponse(ch); + FullHttpResponse response = responses.remove(); assertEquals(BAD_REQUEST, response.getStatus()); assertEquals("not a WebSocket request: missing key", getResponseMessage(response)); } @@ -101,22 +109,26 @@ public class WebSocketServerProtocolHandlerTest { @Test public void testHandleTextFrame() { CustomTextFrameHandler customTextFrameHandler = new CustomTextFrameHandler(); - EmbeddedMessageChannel ch = createChannel(customTextFrameHandler); + EmbeddedChannel ch = createChannel(customTextFrameHandler); writeUpgradeRequest(ch); - // Removing the HttpRequestDecoder as we are writing a TextWebSocketFrame so decoding is not neccessary. - ch.pipeline().remove(HttpRequestDecoder.class); + + if (ch.pipeline().context(HttpRequestDecoder.class) != null) { + // Removing the HttpRequestDecoder because we are writing a TextWebSocketFrame and thus + // decoding is not neccessary. + ch.pipeline().remove(HttpRequestDecoder.class); + } ch.writeInbound(new TextWebSocketFrame("payload")); assertEquals("processed: payload", customTextFrameHandler.getContent()); } - private static EmbeddedMessageChannel createChannel() { + private EmbeddedChannel createChannel() { return createChannel(null); } - private static EmbeddedMessageChannel createChannel(ChannelHandler handler) { - return new EmbeddedMessageChannel( + private EmbeddedChannel createChannel(ChannelHandler handler) { + return new EmbeddedChannel( new WebSocketServerProtocolHandler("/test", null, false), new HttpRequestDecoder(), new HttpResponseEncoder(), @@ -124,7 +136,7 @@ public class WebSocketServerProtocolHandlerTest { handler); } - private static void writeUpgradeRequest(EmbeddedMessageChannel ch) { + private static void writeUpgradeRequest(EmbeddedChannel ch) { ch.writeInbound(WebSocketRequestBuilder.sucessful()); } @@ -132,31 +144,25 @@ public class WebSocketServerProtocolHandlerTest { return new String(response.content().array()); } - private static FullHttpResponse getHttpResponse(EmbeddedMessageChannel ch) { - MessageBuf outbound = ch.pipeline().context(MockOutboundHandler.class).outboundMessageBuffer(); - return (FullHttpResponse) outbound.poll(); - } - - private static class MockOutboundHandler - extends ChannelOperationHandlerAdapter implements ChannelOutboundMessageHandler { + private class MockOutboundHandler extends ChannelOutboundHandlerAdapter { @Override - public MessageBuf newOutboundBuffer(ChannelHandlerContext ctx) throws Exception { - return Unpooled.messageBuffer(); - } - - @Override - public void flush(ChannelHandlerContext ctx, ChannelPromise future) throws Exception { - //NoOp + public void write(ChannelHandlerContext ctx, MessageList msgs, ChannelPromise promise) + throws Exception { + for (int i = 0; i < msgs.size(); i++) { + responses.add((FullHttpResponse) msgs.get(i)); + } + promise.setSuccess(); } } - private static class CustomTextFrameHandler extends ChannelInboundMessageHandlerAdapter { + private static class CustomTextFrameHandler extends ChannelInboundHandlerAdapter { private String content; @Override - public void messageReceived(ChannelHandlerContext ctx, TextWebSocketFrame msg) throws Exception { - content = "processed: " + msg.text(); + public void messageReceived(ChannelHandlerContext ctx, MessageList msgs) throws Exception { + assertEquals(1, msgs.size()); + content = "processed: " + ((TextWebSocketFrame) msgs.get(0)).text(); } String getContent() { diff --git a/codec-http/src/test/java/io/netty/handler/codec/spdy/SpdySessionHandlerTest.java b/codec-http/src/test/java/io/netty/handler/codec/spdy/SpdySessionHandlerTest.java index bd18a2b6a5..7515ceb888 100644 --- a/codec-http/src/test/java/io/netty/handler/codec/spdy/SpdySessionHandlerTest.java +++ b/codec-http/src/test/java/io/netty/handler/codec/spdy/SpdySessionHandlerTest.java @@ -16,8 +16,9 @@ package io.netty.handler.codec.spdy; import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.ChannelInboundMessageHandlerAdapter; -import io.netty.channel.embedded.EmbeddedMessageChannel; +import io.netty.channel.ChannelInboundHandlerAdapter; +import io.netty.channel.MessageList; +import io.netty.channel.embedded.EmbeddedChannel; import io.netty.util.internal.logging.InternalLogger; import io.netty.util.internal.logging.InternalLoggerFactory; import org.junit.Test; @@ -99,7 +100,7 @@ public class SpdySessionHandlerTest { } private static void testSpdySessionHandler(int version, boolean server) { - EmbeddedMessageChannel sessionHandler = new EmbeddedMessageChannel( + EmbeddedChannel sessionHandler = new EmbeddedChannel( new SpdySessionHandler(version, server), new EchoHandler(closeSignal, server)); while (sessionHandler.readOutbound() != null) { @@ -278,7 +279,7 @@ public class SpdySessionHandlerTest { // Echo Handler opens 4 half-closed streams on session connection // and then sets the number of concurrent streams to 3 - private static class EchoHandler extends ChannelInboundMessageHandlerAdapter { + private static class EchoHandler extends ChannelInboundHandlerAdapter { private final int closeSignal; private final boolean server; @@ -309,35 +310,38 @@ public class SpdySessionHandlerTest { } @Override - public void messageReceived(ChannelHandlerContext ctx, Object msg) throws Exception { - if (msg instanceof SpdyDataFrame || - msg instanceof SpdyPingFrame || - msg instanceof SpdyHeadersFrame) { + public void messageReceived(ChannelHandlerContext ctx, MessageList messages) throws Exception { + for (int i = 0; i < messages.size(); i++) { + Object msg = messages.get(i); + if (msg instanceof SpdyDataFrame || + msg instanceof SpdyPingFrame || + msg instanceof SpdyHeadersFrame) { - ctx.write(msg); - return; - } - - if (msg instanceof SpdySynStreamFrame) { - - SpdySynStreamFrame spdySynStreamFrame = (SpdySynStreamFrame) msg; - if (!spdySynStreamFrame.isUnidirectional()) { - int streamID = spdySynStreamFrame.getStreamId(); - SpdySynReplyFrame spdySynReplyFrame = new DefaultSpdySynReplyFrame(streamID); - spdySynReplyFrame.setLast(spdySynStreamFrame.isLast()); - for (Map.Entry entry: spdySynStreamFrame.headers()) { - spdySynReplyFrame.headers().add(entry.getKey(), entry.getValue()); - } - - ctx.write(spdySynReplyFrame); + ctx.write(msg); + return; } - return; - } - if (msg instanceof SpdySettingsFrame) { - SpdySettingsFrame spdySettingsFrame = (SpdySettingsFrame) msg; - if (spdySettingsFrame.isSet(closeSignal)) { - ctx.close(); + if (msg instanceof SpdySynStreamFrame) { + + SpdySynStreamFrame spdySynStreamFrame = (SpdySynStreamFrame) msg; + if (!spdySynStreamFrame.isUnidirectional()) { + int streamID = spdySynStreamFrame.getStreamId(); + SpdySynReplyFrame spdySynReplyFrame = new DefaultSpdySynReplyFrame(streamID); + spdySynReplyFrame.setLast(spdySynStreamFrame.isLast()); + for (Map.Entry entry: spdySynStreamFrame.headers()) { + spdySynReplyFrame.headers().add(entry.getKey(), entry.getValue()); + } + + ctx.write(spdySynReplyFrame); + } + return; + } + + if (msg instanceof SpdySettingsFrame) { + SpdySettingsFrame spdySettingsFrame = (SpdySettingsFrame) msg; + if (spdySettingsFrame.isSet(closeSignal)) { + ctx.close(); + } } } } diff --git a/codec-socks/pom.xml b/codec-socks/pom.xml index 5e5806e6e2..2771f57ac1 100644 --- a/codec-socks/pom.xml +++ b/codec-socks/pom.xml @@ -20,7 +20,7 @@ io.netty netty-parent - 4.0.0.Final-SNAPSHOT + 4.0.0.CR4-SNAPSHOT netty-codec-socks diff --git a/codec-socks/src/main/java/io/netty/handler/codec/socks/SocksAuthRequestDecoder.java b/codec-socks/src/main/java/io/netty/handler/codec/socks/SocksAuthRequestDecoder.java index 53101ed862..d298fd4917 100644 --- a/codec-socks/src/main/java/io/netty/handler/codec/socks/SocksAuthRequestDecoder.java +++ b/codec-socks/src/main/java/io/netty/handler/codec/socks/SocksAuthRequestDecoder.java @@ -16,8 +16,8 @@ package io.netty.handler.codec.socks; import io.netty.buffer.ByteBuf; -import io.netty.buffer.MessageBuf; import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.MessageList; import io.netty.handler.codec.ReplayingDecoder; import io.netty.util.CharsetUtil; @@ -43,7 +43,7 @@ public class SocksAuthRequestDecoder extends ReplayingDecoder out) throws Exception { + protected void decode(ChannelHandlerContext ctx, ByteBuf byteBuf, MessageList out) throws Exception { switch (state()) { case CHECK_PROTOCOL_VERSION: { version = SocksSubnegotiationVersion.fromByte(byteBuf.readByte()); diff --git a/codec-socks/src/main/java/io/netty/handler/codec/socks/SocksAuthResponseDecoder.java b/codec-socks/src/main/java/io/netty/handler/codec/socks/SocksAuthResponseDecoder.java index 7ba8db8d94..01ed2c2979 100644 --- a/codec-socks/src/main/java/io/netty/handler/codec/socks/SocksAuthResponseDecoder.java +++ b/codec-socks/src/main/java/io/netty/handler/codec/socks/SocksAuthResponseDecoder.java @@ -16,8 +16,8 @@ package io.netty.handler.codec.socks; import io.netty.buffer.ByteBuf; -import io.netty.buffer.MessageBuf; import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.MessageList; import io.netty.handler.codec.ReplayingDecoder; /** @@ -40,7 +40,7 @@ public class SocksAuthResponseDecoder extends ReplayingDecoder out) + protected void decode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, MessageList out) throws Exception { switch (state()) { case CHECK_PROTOCOL_VERSION: { diff --git a/codec-socks/src/main/java/io/netty/handler/codec/socks/SocksCmdRequestDecoder.java b/codec-socks/src/main/java/io/netty/handler/codec/socks/SocksCmdRequestDecoder.java index feadc09982..b85df155e9 100644 --- a/codec-socks/src/main/java/io/netty/handler/codec/socks/SocksCmdRequestDecoder.java +++ b/codec-socks/src/main/java/io/netty/handler/codec/socks/SocksCmdRequestDecoder.java @@ -16,8 +16,8 @@ package io.netty.handler.codec.socks; import io.netty.buffer.ByteBuf; -import io.netty.buffer.MessageBuf; import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.MessageList; import io.netty.handler.codec.ReplayingDecoder; import io.netty.util.CharsetUtil; @@ -46,7 +46,7 @@ public class SocksCmdRequestDecoder extends ReplayingDecoder out) throws Exception { + protected void decode(ChannelHandlerContext ctx, ByteBuf byteBuf, MessageList out) throws Exception { switch (state()) { case CHECK_PROTOCOL_VERSION: { version = SocksProtocolVersion.fromByte(byteBuf.readByte()); diff --git a/codec-socks/src/main/java/io/netty/handler/codec/socks/SocksCmdResponseDecoder.java b/codec-socks/src/main/java/io/netty/handler/codec/socks/SocksCmdResponseDecoder.java index 3670a36dcc..203005dd2d 100644 --- a/codec-socks/src/main/java/io/netty/handler/codec/socks/SocksCmdResponseDecoder.java +++ b/codec-socks/src/main/java/io/netty/handler/codec/socks/SocksCmdResponseDecoder.java @@ -16,8 +16,8 @@ package io.netty.handler.codec.socks; import io.netty.buffer.ByteBuf; -import io.netty.buffer.MessageBuf; import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.MessageList; import io.netty.handler.codec.ReplayingDecoder; import io.netty.util.CharsetUtil; @@ -46,7 +46,7 @@ public class SocksCmdResponseDecoder extends ReplayingDecoder out) throws Exception { + protected void decode(ChannelHandlerContext ctx, ByteBuf byteBuf, MessageList out) throws Exception { switch (state()) { case CHECK_PROTOCOL_VERSION: { version = SocksProtocolVersion.fromByte(byteBuf.readByte()); diff --git a/codec-socks/src/main/java/io/netty/handler/codec/socks/SocksInitRequestDecoder.java b/codec-socks/src/main/java/io/netty/handler/codec/socks/SocksInitRequestDecoder.java index 30102c077c..16c0b7221d 100644 --- a/codec-socks/src/main/java/io/netty/handler/codec/socks/SocksInitRequestDecoder.java +++ b/codec-socks/src/main/java/io/netty/handler/codec/socks/SocksInitRequestDecoder.java @@ -16,8 +16,8 @@ package io.netty.handler.codec.socks; import io.netty.buffer.ByteBuf; -import io.netty.buffer.MessageBuf; import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.MessageList; import io.netty.handler.codec.ReplayingDecoder; import java.util.ArrayList; @@ -44,7 +44,7 @@ public class SocksInitRequestDecoder extends ReplayingDecoder out) throws Exception { + protected void decode(ChannelHandlerContext ctx, ByteBuf byteBuf, MessageList out) throws Exception { switch (state()) { case CHECK_PROTOCOL_VERSION: { version = SocksProtocolVersion.fromByte(byteBuf.readByte()); diff --git a/codec-socks/src/main/java/io/netty/handler/codec/socks/SocksInitResponseDecoder.java b/codec-socks/src/main/java/io/netty/handler/codec/socks/SocksInitResponseDecoder.java index 1978269363..e5c07a2a1c 100644 --- a/codec-socks/src/main/java/io/netty/handler/codec/socks/SocksInitResponseDecoder.java +++ b/codec-socks/src/main/java/io/netty/handler/codec/socks/SocksInitResponseDecoder.java @@ -16,8 +16,8 @@ package io.netty.handler.codec.socks; import io.netty.buffer.ByteBuf; -import io.netty.buffer.MessageBuf; import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.MessageList; import io.netty.handler.codec.ReplayingDecoder; /** @@ -41,7 +41,7 @@ public class SocksInitResponseDecoder extends ReplayingDecoder out) throws Exception { + protected void decode(ChannelHandlerContext ctx, ByteBuf byteBuf, MessageList out) throws Exception { switch (state()) { case CHECK_PROTOCOL_VERSION: { version = SocksProtocolVersion.fromByte(byteBuf.readByte()); diff --git a/codec-socks/src/test/java/io/netty/handler/codec/socks/SocksAuthRequestDecoderTest.java b/codec-socks/src/test/java/io/netty/handler/codec/socks/SocksAuthRequestDecoderTest.java index a94bbeec24..ff8692a521 100644 --- a/codec-socks/src/test/java/io/netty/handler/codec/socks/SocksAuthRequestDecoderTest.java +++ b/codec-socks/src/test/java/io/netty/handler/codec/socks/SocksAuthRequestDecoderTest.java @@ -15,7 +15,7 @@ */ package io.netty.handler.codec.socks; -import io.netty.channel.embedded.EmbeddedByteChannel; +import io.netty.channel.embedded.EmbeddedChannel; import org.junit.Test; import static org.junit.Assert.*; @@ -28,7 +28,7 @@ public class SocksAuthRequestDecoderTest { String password = "test"; SocksAuthRequest msg = new SocksAuthRequest(username, password); SocksAuthRequestDecoder decoder = new SocksAuthRequestDecoder(); - EmbeddedByteChannel embedder = new EmbeddedByteChannel(decoder); + EmbeddedChannel embedder = new EmbeddedChannel(decoder); SocksCommonTestUtils.writeMessageIntoEmbedder(embedder, msg); msg = (SocksAuthRequest) embedder.readInbound(); assertEquals(msg.username(), username); diff --git a/codec-socks/src/test/java/io/netty/handler/codec/socks/SocksAuthResponseDecoderTest.java b/codec-socks/src/test/java/io/netty/handler/codec/socks/SocksAuthResponseDecoderTest.java index ad88597a4d..1604f53bb9 100644 --- a/codec-socks/src/test/java/io/netty/handler/codec/socks/SocksAuthResponseDecoderTest.java +++ b/codec-socks/src/test/java/io/netty/handler/codec/socks/SocksAuthResponseDecoderTest.java @@ -15,7 +15,7 @@ */ package io.netty.handler.codec.socks; -import io.netty.channel.embedded.EmbeddedByteChannel; +import io.netty.channel.embedded.EmbeddedChannel; import io.netty.util.internal.logging.InternalLogger; import io.netty.util.internal.logging.InternalLoggerFactory; import org.junit.Test; @@ -29,7 +29,7 @@ public class SocksAuthResponseDecoderTest { logger.debug("Testing SocksAuthResponseDecoder with authStatus: " + authStatus); SocksAuthResponse msg = new SocksAuthResponse(authStatus); SocksAuthResponseDecoder decoder = new SocksAuthResponseDecoder(); - EmbeddedByteChannel embedder = new EmbeddedByteChannel(decoder); + EmbeddedChannel embedder = new EmbeddedChannel(decoder); SocksCommonTestUtils.writeMessageIntoEmbedder(embedder, msg); msg = (SocksAuthResponse) embedder.readInbound(); assertSame(msg.authStatus(), authStatus); diff --git a/codec-socks/src/test/java/io/netty/handler/codec/socks/SocksCmdRequestDecoderTest.java b/codec-socks/src/test/java/io/netty/handler/codec/socks/SocksCmdRequestDecoderTest.java index 32de008844..8ae2a726db 100644 --- a/codec-socks/src/test/java/io/netty/handler/codec/socks/SocksCmdRequestDecoderTest.java +++ b/codec-socks/src/test/java/io/netty/handler/codec/socks/SocksCmdRequestDecoderTest.java @@ -15,7 +15,7 @@ */ package io.netty.handler.codec.socks; -import io.netty.channel.embedded.EmbeddedByteChannel; +import io.netty.channel.embedded.EmbeddedChannel; import io.netty.util.internal.logging.InternalLogger; import io.netty.util.internal.logging.InternalLoggerFactory; import org.junit.Test; @@ -34,7 +34,7 @@ public class SocksCmdRequestDecoderTest { " port: " + port); SocksCmdRequest msg = new SocksCmdRequest(cmdType, addressType, host, port); SocksCmdRequestDecoder decoder = new SocksCmdRequestDecoder(); - EmbeddedByteChannel embedder = new EmbeddedByteChannel(decoder); + EmbeddedChannel embedder = new EmbeddedChannel(decoder); SocksCommonTestUtils.writeMessageIntoEmbedder(embedder, msg); if (msg.addressType() == SocksAddressType.UNKNOWN) { assertTrue(embedder.readInbound() instanceof UnknownSocksRequest); diff --git a/codec-socks/src/test/java/io/netty/handler/codec/socks/SocksCmdResponseDecoderTest.java b/codec-socks/src/test/java/io/netty/handler/codec/socks/SocksCmdResponseDecoderTest.java index f058780d36..9f2691dc96 100644 --- a/codec-socks/src/test/java/io/netty/handler/codec/socks/SocksCmdResponseDecoderTest.java +++ b/codec-socks/src/test/java/io/netty/handler/codec/socks/SocksCmdResponseDecoderTest.java @@ -15,7 +15,7 @@ */ package io.netty.handler.codec.socks; -import io.netty.channel.embedded.EmbeddedByteChannel; +import io.netty.channel.embedded.EmbeddedChannel; import io.netty.util.internal.logging.InternalLogger; import io.netty.util.internal.logging.InternalLoggerFactory; import org.junit.Test; @@ -25,12 +25,12 @@ import static org.junit.Assert.*; public class SocksCmdResponseDecoderTest { private static final InternalLogger logger = InternalLoggerFactory.getInstance(SocksCmdResponseDecoderTest.class); - private static void testSocksCmdResponseDecoderWithDifferentParams(SocksCmdStatus cmdStatus, - SocksAddressType addressType) { + private static void testSocksCmdResponseDecoderWithDifferentParams( + SocksCmdStatus cmdStatus, SocksAddressType addressType) { logger.debug("Testing cmdStatus: " + cmdStatus + " addressType: " + addressType); SocksResponse msg = new SocksCmdResponse(cmdStatus, addressType); SocksCmdResponseDecoder decoder = new SocksCmdResponseDecoder(); - EmbeddedByteChannel embedder = new EmbeddedByteChannel(decoder); + EmbeddedChannel embedder = new EmbeddedChannel(decoder); SocksCommonTestUtils.writeMessageIntoEmbedder(embedder, msg); if (addressType == SocksAddressType.UNKNOWN) { assertTrue(embedder.readInbound() instanceof UnknownSocksResponse); diff --git a/codec-socks/src/test/java/io/netty/handler/codec/socks/SocksCommonTestUtils.java b/codec-socks/src/test/java/io/netty/handler/codec/socks/SocksCommonTestUtils.java index ade7a7e417..f4a54dbad0 100644 --- a/codec-socks/src/test/java/io/netty/handler/codec/socks/SocksCommonTestUtils.java +++ b/codec-socks/src/test/java/io/netty/handler/codec/socks/SocksCommonTestUtils.java @@ -17,7 +17,7 @@ package io.netty.handler.codec.socks; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; -import io.netty.channel.embedded.EmbeddedByteChannel; +import io.netty.channel.embedded.EmbeddedChannel; final class SocksCommonTestUtils { /** @@ -27,7 +27,7 @@ final class SocksCommonTestUtils { //NOOP } - public static void writeMessageIntoEmbedder(EmbeddedByteChannel embedder, SocksMessage msg) { + public static void writeMessageIntoEmbedder(EmbeddedChannel embedder, SocksMessage msg) { ByteBuf buf = Unpooled.buffer(); msg.encodeAsByteBuf(buf); embedder.writeInbound(buf); diff --git a/codec/pom.xml b/codec/pom.xml index b12012909f..a11717c764 100644 --- a/codec/pom.xml +++ b/codec/pom.xml @@ -20,7 +20,7 @@ io.netty netty-parent - 4.0.0.Final-SNAPSHOT + 4.0.0.CR4-SNAPSHOT netty-codec diff --git a/codec/src/main/java/io/netty/handler/codec/ByteToByteCodec.java b/codec/src/main/java/io/netty/handler/codec/ByteToByteCodec.java deleted file mode 100644 index 2907e6a00a..0000000000 --- a/codec/src/main/java/io/netty/handler/codec/ByteToByteCodec.java +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Copyright 2012 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; - -import io.netty.buffer.ByteBuf; -import io.netty.channel.ChannelDuplexHandler; -import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.ChannelInboundByteHandler; -import io.netty.channel.ChannelOutboundByteHandler; -import io.netty.channel.ChannelPromise; - -/** - * A Codec for on-the-fly encoding/decoding of bytes. - * - * This can be thought of as a combination of {@link ByteToByteDecoder} and {@link ByteToByteEncoder}. - * - * Here is an example of a {@link ByteToByteCodec} which just square {@link Integer} read from a {@link ByteBuf}. - * - * public class SquareCodec extends {@link ByteToByteCodec} { - * {@code @Override} - * public void decode({@link ChannelHandlerContext} ctx, {@link ByteBuf} in, {@link ByteBuf} out) - * throws {@link Exception} { - * if (in.readableBytes() < 4) { - * return; - * } - * int value = in.readInt(); - * out.writeInt(value * value); - * } - * - * {@code @Overrride} - * public void encode({@link ChannelHandlerContext} ctx, {@link ByteBuf} in, {@link ByteBuf} out) - * throws {@link Exception} { - * if (in.readableBytes() < 4) { - * return; - * } - * int value = in.readInt(); - * out.writeInt(value / value); - * } - * } - * - */ -public abstract class ByteToByteCodec - extends ChannelDuplexHandler - implements ChannelInboundByteHandler, ChannelOutboundByteHandler { - - private final ByteToByteEncoder encoder = new ByteToByteEncoder() { - @Override - protected void encode( - ChannelHandlerContext ctx, - ByteBuf in, ByteBuf out) throws Exception { - ByteToByteCodec.this.encode(ctx, in, out); - } - }; - - private final ByteToByteDecoder decoder = new ByteToByteDecoder() { - @Override - protected void decode(ChannelHandlerContext ctx, ByteBuf in, ByteBuf out) throws Exception { - ByteToByteCodec.this.decode(ctx, in, out); - } - - @Override - protected void decodeLast(ChannelHandlerContext ctx, ByteBuf in, ByteBuf out) throws Exception { - ByteToByteCodec.this.decodeLast(ctx, in, out); - } - }; - - @Override - public ByteBuf newInboundBuffer(ChannelHandlerContext ctx) throws Exception { - return decoder.newInboundBuffer(ctx); - } - - @Override - public void inboundBufferUpdated(ChannelHandlerContext ctx) throws Exception { - decoder.inboundBufferUpdated(ctx); - } - - @Override - public ByteBuf newOutboundBuffer(ChannelHandlerContext ctx) throws Exception { - return encoder.newOutboundBuffer(ctx); - } - - @Override - public void flush( - ChannelHandlerContext ctx, ChannelPromise promise) throws Exception { - encoder.flush(ctx, promise); - } - - @Override - public void discardInboundReadBytes(ChannelHandlerContext ctx) throws Exception { - decoder.discardInboundReadBytes(ctx); - } - - @Override - public void discardOutboundReadBytes(ChannelHandlerContext ctx) throws Exception { - encoder.discardOutboundReadBytes(ctx); - } - - /** - * @see {@link ByteToByteEncoder#encode(ChannelHandlerContext, ByteBuf, ByteBuf)} - */ - protected abstract void encode(ChannelHandlerContext ctx, ByteBuf in, ByteBuf out) throws Exception; - - /** - * @see {@link ByteToByteDecoder#decode(ChannelHandlerContext, ByteBuf, ByteBuf)} - */ - protected abstract void decode(ChannelHandlerContext ctx, ByteBuf in, ByteBuf out) throws Exception; - - /** - * @see {@link ByteToByteDecoder#decodeLast(ChannelHandlerContext, ByteBuf, ByteBuf)} - */ - protected void decodeLast(ChannelHandlerContext ctx, ByteBuf in, ByteBuf out) throws Exception { - decode(ctx, in, out); - } -} diff --git a/codec/src/main/java/io/netty/handler/codec/ByteToByteDecoder.java b/codec/src/main/java/io/netty/handler/codec/ByteToByteDecoder.java deleted file mode 100644 index a2ad13ead7..0000000000 --- a/codec/src/main/java/io/netty/handler/codec/ByteToByteDecoder.java +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright 2012 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; - -import io.netty.buffer.ByteBuf; -import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.ChannelInboundByteHandlerAdapter; - -/** - * {@link ChannelInboundByteHandlerAdapter} which decodes bytes in a stream-like fashion from one {@link ByteBuf} to an - * other. - * - * This kind of decoder is often useful for doing on-the-fly processiing like i.e. compression. - * - * But you can also do other things with it. For example here is an implementation which reads {@link Integer}s from - * the input {@link ByteBuf} and square them before write them to the output {@link ByteBuf}. - * - * - * public class SquareDecoder extends {@link ByteToByteDecoder} { - * {@code @Override} - * public void decode({@link ChannelHandlerContext} ctx, {@link ByteBuf} in, {@link ByteBuf} out) - * throws {@link Exception} { - * if (in.readableBytes() < 4) { - * return; - * } - * int value = in.readInt(); - * out.writeInt(value * value); - * } - * } - * - */ -public abstract class ByteToByteDecoder extends ChannelInboundByteHandlerAdapter { - - private volatile boolean singleDecode; - - /** - * If set then only one message is decoded on each {@link #inboundBufferUpdated(ChannelHandlerContext)} call. - * This may be useful if you need to do some protocol upgrade and want to make sure nothing is mixed up. - * - * Default is {@code false} as this has performance impacts. - */ - public void setSingleDecode(boolean singleDecode) { - this.singleDecode = singleDecode; - } - - /** - * If {@code true} then only one message is decoded on each - * {@link #inboundBufferUpdated(ChannelHandlerContext)} call. - * - * Default is {@code false} as this has performance impacts. - */ - public boolean isSingleDecode() { - return singleDecode; - } - - @Override - public void inboundBufferUpdated(ChannelHandlerContext ctx, ByteBuf in) throws Exception { - callDecode(ctx, in, ctx.nextInboundByteBuffer()); - } - - @Override - public void channelInactive(ChannelHandlerContext ctx) throws Exception { - ByteBuf in = ctx.inboundByteBuffer(); - ByteBuf out = ctx.nextInboundByteBuffer(); - if (!in.isReadable()) { - callDecode(ctx, in, out); - } - - int oldOutSize = out.readableBytes(); - try { - decodeLast(ctx, in, out); - } catch (CodecException e) { - throw e; - } catch (Throwable t) { - throw new DecoderException(t); - } finally { - if (out.readableBytes() > oldOutSize) { - ctx.fireInboundBufferUpdated(); - } - ctx.fireChannelInactive(); - } - } - - /** - * Call the {@link #decode(ChannelHandlerContext, ByteBuf, ByteBuf)} method until it is done. - */ - private void callDecode(ChannelHandlerContext ctx, ByteBuf in, ByteBuf out) { - int oldOutSize = out.readableBytes(); - try { - while (in.isReadable()) { - int oldInSize = in.readableBytes(); - decode(ctx, in, out); - if (oldInSize == in.readableBytes() || isSingleDecode()) { - break; - } - } - } catch (CodecException e) { - throw e; - } catch (Throwable t) { - throw new DecoderException(t); - } finally { - if (out.readableBytes() > oldOutSize) { - ctx.fireInboundBufferUpdated(); - } - } - } - - /** - * Decode the from one {@link ByteBuf} to an other. This method will be called till either the input - * {@link ByteBuf} has nothing to read anymore or till nothing was read from the input {@link ByteBuf}. - * - * @param ctx the {@link ChannelHandlerContext} which this {@link ByteToByteDecoder} belongs to - * @param in the {@link ByteBuf} from which to read data - * @param out the {@link ByteBuf} to which the decoded data will be written - * @throws Exception is thrown if an error accour - */ - protected abstract void decode(ChannelHandlerContext ctx, ByteBuf in, ByteBuf out) throws Exception; - - /** - * Is called one last time when the {@link ChannelHandlerContext} goes in-active. Which means the - * {@link #channelInactive(ChannelHandlerContext)} was triggered. - * - * By default this will just call {@link #decode(ChannelHandlerContext, ByteBuf, ByteBuf)} but sub-classes may - * override this for some special cleanup operation. - */ - protected void decodeLast(ChannelHandlerContext ctx, ByteBuf in, ByteBuf out) throws Exception { - decode(ctx, in, out); - } -} diff --git a/codec/src/main/java/io/netty/handler/codec/ByteToByteEncoder.java b/codec/src/main/java/io/netty/handler/codec/ByteToByteEncoder.java deleted file mode 100644 index f1ed0f9212..0000000000 --- a/codec/src/main/java/io/netty/handler/codec/ByteToByteEncoder.java +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Copyright 2012 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; - -import io.netty.buffer.ByteBuf; -import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.ChannelOutboundByteHandlerAdapter; -import io.netty.channel.ChannelPromise; -import io.netty.channel.FileRegion; -import io.netty.channel.IncompleteFlushException; - -import java.io.EOFException; -import java.io.IOException; -import java.nio.ByteBuffer; -import java.nio.channels.WritableByteChannel; - -/** - * {@link ChannelOutboundByteHandlerAdapter} which encodes bytes in a stream-like fashion from one {@link ByteBuf} to an - * other. - * - * This kind of decoder is often useful for doing on-the-fly processing like i.e. compression. - * - * But you can also do other things with it. For example here is an implementation which reads {@link Integer}s from - * the input {@link ByteBuf} and square them before write them to the output {@link ByteBuf}. - * - * - * public class SquareEncoder extends {@link ByteToByteEncoder} { - * {@code @Override} - * public void encode({@link ChannelHandlerContext} ctx, {@link ByteBuf} in, {@link ByteBuf} out) - * throws {@link Exception} { - * if (in.readableBytes() < 4) { - * return; - * } - * int value = in.readInt(); - * out.writeInt(value * value); - * } - * } - * - */ -public abstract class ByteToByteEncoder extends ChannelOutboundByteHandlerAdapter { - - @Override - protected void flush(ChannelHandlerContext ctx, ByteBuf in, ChannelPromise promise) throws Exception { - ByteBuf out = ctx.nextOutboundByteBuffer(); - boolean encoded = false; - - try { - while (in.isReadable()) { - int oldInSize = in.readableBytes(); - encode(ctx, in, out); - encoded = true; - if (oldInSize == in.readableBytes()) { - break; - } - } - } catch (Throwable t) { - if (!(t instanceof CodecException)) { - t = new EncoderException(t); - } - if (encoded) { - t = new IncompleteFlushException("unable to encode all bytes", t); - } - in.discardSomeReadBytes(); - promise.setFailure(t); - return; - } - - ctx.flush(promise); - } - - @Override - public void sendFile(ChannelHandlerContext ctx, FileRegion region, ChannelPromise promise) throws Exception { - long written = 0; - try { - for (;;) { - long localWritten = region.transferTo(new BufferChannel(ctx.outboundByteBuffer()), written); - if (localWritten == -1) { - checkEOF(region, written); - flush(ctx, promise); - break; - } - written += localWritten; - if (written >= region.count()) { - flush(ctx, promise); - break; - } - } - } catch (IOException e) { - promise.setFailure(new EncoderException(e)); - } finally { - region.release(); - } - } - - private static void checkEOF(FileRegion region, long writtenBytes) throws IOException { - if (writtenBytes < region.count()) { - throw new EOFException("Expected to be able to write " - + region.count() + " bytes, but only wrote " - + writtenBytes); - } - } - - private static final class BufferChannel implements WritableByteChannel { - private final ByteBuf buffer; - - BufferChannel(ByteBuf buffer) { - this.buffer = buffer; - } - @Override - public int write(ByteBuffer src) { - int bytes = src.remaining(); - buffer.writeBytes(src); - return bytes; - } - - @Override - public boolean isOpen() { - return buffer.refCnt() > 0; - } - - @Override - public void close() { - // NOOP - } - } - - /** - * Encodes the from one {@link ByteBuf} to an other. This method will be called till either the input - * {@link ByteBuf} has nothing to read anymore or till nothing was read from the input {@link ByteBuf}. - * - * @param ctx the {@link ChannelHandlerContext} which this {@link ByteToByteDecoder} belongs to - * @param in the {@link ByteBuf} from which to read data - * @param out the {@link ByteBuf} to which the decoded data will be written - * @throws Exception is thrown if an error accour - */ - protected abstract void encode(ChannelHandlerContext ctx, ByteBuf in, ByteBuf out) throws Exception; -} diff --git a/codec/src/main/java/io/netty/handler/codec/ByteToMessageCodec.java b/codec/src/main/java/io/netty/handler/codec/ByteToMessageCodec.java index b44331b4b6..7622510c35 100644 --- a/codec/src/main/java/io/netty/handler/codec/ByteToMessageCodec.java +++ b/codec/src/main/java/io/netty/handler/codec/ByteToMessageCodec.java @@ -16,16 +16,13 @@ package io.netty.handler.codec; import io.netty.buffer.ByteBuf; -import io.netty.buffer.MessageBuf; import io.netty.channel.ChannelDuplexHandler; import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.ChannelInboundByteHandler; -import io.netty.channel.ChannelOutboundMessageHandler; import io.netty.channel.ChannelPromise; +import io.netty.channel.MessageList; import io.netty.util.internal.TypeParameterMatcher; -public abstract class ByteToMessageCodec extends ChannelDuplexHandler - implements ChannelInboundByteHandler, ChannelOutboundMessageHandler { +public abstract class ByteToMessageCodec extends ChannelDuplexHandler { private final TypeParameterMatcher outboundMsgMatcher; private final MessageToByteEncoder encoder = new MessageToByteEncoder() { @@ -42,12 +39,12 @@ public abstract class ByteToMessageCodec extends ChannelDuplexHandler private final ByteToMessageDecoder decoder = new ByteToMessageDecoder() { @Override - public void decode(ChannelHandlerContext ctx, ByteBuf in, MessageBuf out) throws Exception { + public void decode(ChannelHandlerContext ctx, ByteBuf in, MessageList out) throws Exception { ByteToMessageCodec.this.decode(ctx, in, out); } @Override - protected void decodeLast(ChannelHandlerContext ctx, ByteBuf in, MessageBuf out) throws Exception { + protected void decodeLast(ChannelHandlerContext ctx, ByteBuf in, MessageList out) throws Exception { ByteToMessageCodec.this.decodeLast(ctx, in, out); } }; @@ -60,38 +57,23 @@ public abstract class ByteToMessageCodec extends ChannelDuplexHandler outboundMsgMatcher = TypeParameterMatcher.get(outboundMessageType); } - @Override - public ByteBuf newInboundBuffer(ChannelHandlerContext ctx) throws Exception { - return decoder.newInboundBuffer(ctx); - } - - @Override - public void discardInboundReadBytes(ChannelHandlerContext ctx) throws Exception { - decoder.discardInboundReadBytes(ctx); - } - - @Override - public MessageBuf newOutboundBuffer(ChannelHandlerContext ctx) throws Exception { - return encoder.newOutboundBuffer(ctx); - } - - @Override - public void inboundBufferUpdated(ChannelHandlerContext ctx) throws Exception { - decoder.inboundBufferUpdated(ctx); - } - - @Override - public void flush(ChannelHandlerContext ctx, ChannelPromise promise) throws Exception { - encoder.flush(ctx, promise); - } - public boolean acceptOutboundMessage(Object msg) throws Exception { return outboundMsgMatcher.match(msg); } + @Override + public void messageReceived(ChannelHandlerContext ctx, MessageList msgs) throws Exception { + decoder.messageReceived(ctx, msgs); + } + + @Override + public void write(ChannelHandlerContext ctx, MessageList msgs, ChannelPromise promise) throws Exception { + encoder.write(ctx, msgs, promise); + } + protected abstract void encode(ChannelHandlerContext ctx, I msg, ByteBuf out) throws Exception; - protected abstract void decode(ChannelHandlerContext ctx, ByteBuf in, MessageBuf out) throws Exception; - protected void decodeLast(ChannelHandlerContext ctx, ByteBuf in, MessageBuf out) throws Exception { + protected abstract void decode(ChannelHandlerContext ctx, ByteBuf in, MessageList out) throws Exception; + protected void decodeLast(ChannelHandlerContext ctx, ByteBuf in, MessageList out) throws Exception { decode(ctx, in, out); } } diff --git a/codec/src/main/java/io/netty/handler/codec/ByteToMessageDecoder.java b/codec/src/main/java/io/netty/handler/codec/ByteToMessageDecoder.java index 6366340c63..7ed8d7fdb7 100644 --- a/codec/src/main/java/io/netty/handler/codec/ByteToMessageDecoder.java +++ b/codec/src/main/java/io/netty/handler/codec/ByteToMessageDecoder.java @@ -16,14 +16,15 @@ package io.netty.handler.codec; import io.netty.buffer.ByteBuf; -import io.netty.buffer.MessageBuf; +import io.netty.buffer.Unpooled; import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.ChannelInboundByteHandler; -import io.netty.channel.ChannelInboundByteHandlerAdapter; +import io.netty.channel.ChannelInboundHandlerAdapter; +import io.netty.channel.MessageList; +import io.netty.util.internal.StringUtil; /** - * {@link ChannelInboundByteHandler} which decodes bytes in a stream-like fashion from one {@link ByteBuf} to an other - * Message type. + * {@link ChannelInboundHandlerAdapter} which decodes bytes in a stream-like fashion from one {@link ByteBuf} to an + * other Message type. * * For example here is an implementation which reads all readable bytes from * the input {@link ByteBuf} and create a new {@link ByteBuf}. @@ -31,22 +32,24 @@ import io.netty.channel.ChannelInboundByteHandlerAdapter; * * public class SquareDecoder extends {@link ByteToMessageDecoder} { * {@code @Override} - * public void decode({@link ChannelHandlerContext} ctx, {@link ByteBuf} in, {@link MessageBuf} out) + * public void decode({@link ChannelHandlerContext} ctx, {@link ByteBuf} in, {@link MessageList} out) * throws {@link Exception} { * out.add(in.readBytes(in.readableBytes())); * } * } * */ -public abstract class ByteToMessageDecoder - extends ChannelInboundByteHandlerAdapter { +public abstract class ByteToMessageDecoder extends ChannelInboundHandlerAdapter { + protected ByteBuf cumulation; private volatile boolean singleDecode; private boolean decodeWasNull; + private MessageList out; + private boolean removed; /** - * If set then only one message is decoded on each {@link #inboundBufferUpdated(ChannelHandlerContext)} call. - * This may be useful if you need to do some protocol upgrade and want to make sure nothing is mixed up. + * If set then only one message is decoded on each {@link #messageReceived(ChannelHandlerContext, MessageList)} + * call. This may be useful if you need to do some protocol upgrade and want to make sure nothing is mixed up. * * Default is {@code false} as this has performance impacts. */ @@ -56,7 +59,7 @@ public abstract class ByteToMessageDecoder /** * If {@code true} then only one message is decoded on each - * {@link #inboundBufferUpdated(ChannelHandlerContext)} call. + * {@link #messageReceived(ChannelHandlerContext, MessageList)} call. * * Default is {@code false} as this has performance impacts. */ @@ -64,9 +67,119 @@ public abstract class ByteToMessageDecoder return singleDecode; } + /** + * Returns the actual number of readable bytes in the internal cumulative + * buffer of this decoder. You usually do not need to rely on this value + * to write a decoder. Use it only when you must use it at your own risk. + * This method is a shortcut to {@link #internalBuffer() internalBuffer().readableBytes()}. + */ + protected int actualReadableBytes() { + return internalBuffer().readableBytes(); + } + + /** + * Returns the internal cumulative buffer of this decoder. You usually + * do not need to access the internal buffer directly to write a decoder. + * Use it only when you must use it at your own risk. + */ + protected ByteBuf internalBuffer() { + if (cumulation != null) { + return cumulation; + } else { + return Unpooled.EMPTY_BUFFER; + } + } + @Override - public void inboundBufferUpdated(ChannelHandlerContext ctx, ByteBuf in) throws Exception { - callDecode(ctx, in); + public final void handlerRemoved(ChannelHandlerContext ctx) throws Exception { + removed = true; + ByteBuf buf = internalBuffer(); + if (buf.isReadable()) { + if (out == null) { + ctx.fireMessageReceived(buf); + } else { + out.add(buf.copy()); + } + buf.clear(); + } + handlerRemoved0(); + } + + /** + * Gets called after the {@link ByteToMessageDecoder} was removed from the actual context and it doesn't handle + * events anymore. + */ + protected void handlerRemoved0() throws Exception { } + + @Override + public void messageReceived(ChannelHandlerContext ctx, MessageList msgs) throws Exception { + out = MessageList.newInstance(); + try { + int size = msgs.size(); + for (int i = 0; i < size; i ++) { + Object m = msgs.get(i); + // handler was removed in the loop + if (removed) { + out.add(m); + continue; + } + if (m instanceof ByteBuf) { + ByteBuf data = (ByteBuf) m; + if (cumulation == null) { + cumulation = data; + try { + callDecode(ctx, data, out); + } finally { + if (!data.isReadable()) { + cumulation = null; + data.release(); + } + } + } else { + try { + if (cumulation.writerIndex() > cumulation.maxCapacity() - data.readableBytes()) { + ByteBuf oldCumulation = cumulation; + cumulation = ctx.alloc().buffer(oldCumulation.readableBytes() + data.readableBytes()); + cumulation.writeBytes(oldCumulation); + oldCumulation.release(); + } + cumulation.writeBytes(data); + callDecode(ctx, cumulation, out); + } finally { + if (!cumulation.isReadable()) { + cumulation.release(); + cumulation = null; + } else { + cumulation.discardSomeReadBytes(); + } + data.release(); + } + } + } else { + out.add(m); + } + } + } catch (DecoderException e) { + throw e; + } catch (Throwable t) { + throw new DecoderException(t); + } finally { + // release the cumulation if the handler was removed while messages are processed + if (removed) { + if (cumulation != null) { + cumulation.release(); + cumulation = null; + } + removed = false; + } + MessageList out = this.out; + this.out = null; + if (out.isEmpty()) { + decodeWasNull = true; + } + msgs.recycle(); + ctx.fireMessageReceived(out); + } } @Override @@ -82,35 +195,36 @@ public abstract class ByteToMessageDecoder @Override public void channelInactive(ChannelHandlerContext ctx) throws Exception { - OutputMessageBuf out = OutputMessageBuf.get(); + MessageList out = MessageList.newInstance(); try { - ByteBuf in = ctx.inboundByteBuffer(); - if (in.isReadable()) { - callDecode(ctx, in); + if (cumulation != null) { + callDecode(ctx, cumulation, out); + decodeLast(ctx, cumulation, out); + } else { + decodeLast(ctx, Unpooled.EMPTY_BUFFER, out); } - decodeLast(ctx, in, out); - } catch (CodecException e) { + } catch (DecoderException e) { throw e; - } catch (Throwable cause) { - throw new DecoderException(cause); + } catch (Exception e) { + throw new DecoderException(e); } finally { - if (out.drainToNextInbound(ctx)) { - ctx.fireInboundBufferUpdated(); + if (cumulation != null) { + cumulation.release(); + cumulation = null; } + + ctx.fireMessageReceived(out); ctx.fireChannelInactive(); } } - protected void callDecode(ChannelHandlerContext ctx, ByteBuf in) { - boolean wasNull = false; - OutputMessageBuf out = OutputMessageBuf.get(); + protected void callDecode(ChannelHandlerContext ctx, ByteBuf in, MessageList out) { try { while (in.isReadable()) { int outSize = out.size(); int oldInputLength = in.readableBytes(); decode(ctx, in, out); if (outSize == out.size()) { - wasNull = true; if (oldInputLength == in.readableBytes()) { break; } else { @@ -118,10 +232,10 @@ public abstract class ByteToMessageDecoder } } - wasNull = false; if (oldInputLength == in.readableBytes()) { - throw new IllegalStateException( - "decode() did not read anything but decoded a message."); + throw new DecoderException( + StringUtil.simpleClassName(getClass()) + + ".decode() did not read anything but decoded a message."); } if (isSingleDecode()) { @@ -132,15 +246,6 @@ public abstract class ByteToMessageDecoder throw e; } catch (Throwable cause) { throw new DecoderException(cause); - } finally { - if (out.drainToNextInbound(ctx)) { - decodeWasNull = false; - ctx.fireInboundBufferUpdated(); - } else { - if (wasNull) { - decodeWasNull = true; - } - } } } @@ -149,22 +254,22 @@ public abstract class ByteToMessageDecoder * {@link ByteBuf} has nothing to read anymore, till nothing was read from the input {@link ByteBuf} or till * this method returns {@code null}. * - * @param ctx the {@link ChannelHandlerContext} which this {@link ByteToByteDecoder} belongs to + * @param ctx the {@link ChannelHandlerContext} which this {@link ByteToMessageDecoder} belongs to * @param in the {@link ByteBuf} from which to read data - * @param out the {@link MessageBuf} to which decoded messages should be added + * @param out the {@link MessageList} to which decoded messages should be added * @throws Exception is thrown if an error accour */ - protected abstract void decode(ChannelHandlerContext ctx, ByteBuf in, MessageBuf out) throws Exception; + protected abstract void decode(ChannelHandlerContext ctx, ByteBuf in, MessageList out) throws Exception; /** * Is called one last time when the {@link ChannelHandlerContext} goes in-active. Which means the * {@link #channelInactive(ChannelHandlerContext)} was triggered. * - * By default this will just call {@link #decode(ChannelHandlerContext, ByteBuf, MessageBuf)} but sub-classes may + * By default this will just call {@link #decode(ChannelHandlerContext, ByteBuf, MessageList)} but sub-classes may * override this for some special cleanup operation. */ - protected void decodeLast(ChannelHandlerContext ctx, ByteBuf in, MessageBuf out) throws Exception { + protected void decodeLast(ChannelHandlerContext ctx, ByteBuf in, MessageList out) throws Exception { decode(ctx, in, out); } } diff --git a/codec/src/main/java/io/netty/handler/codec/DelimiterBasedFrameDecoder.java b/codec/src/main/java/io/netty/handler/codec/DelimiterBasedFrameDecoder.java index 3d22a7dc83..1a0a02d2fa 100644 --- a/codec/src/main/java/io/netty/handler/codec/DelimiterBasedFrameDecoder.java +++ b/codec/src/main/java/io/netty/handler/codec/DelimiterBasedFrameDecoder.java @@ -16,8 +16,8 @@ package io.netty.handler.codec; import io.netty.buffer.ByteBuf; -import io.netty.buffer.MessageBuf; import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.MessageList; /** * A decoder that splits the received {@link ByteBuf}s by one or more @@ -211,7 +211,7 @@ public class DelimiterBasedFrameDecoder extends ByteToMessageDecoder { } @Override - protected void decode(ChannelHandlerContext ctx, ByteBuf in, MessageBuf out) throws Exception { + protected void decode(ChannelHandlerContext ctx, ByteBuf in, MessageList out) throws Exception { Object decoded = decode(ctx, in); if (decoded != null) { out.add(decoded); diff --git a/codec/src/main/java/io/netty/handler/codec/FixedLengthFrameDecoder.java b/codec/src/main/java/io/netty/handler/codec/FixedLengthFrameDecoder.java index 600c19babd..3cc025e711 100644 --- a/codec/src/main/java/io/netty/handler/codec/FixedLengthFrameDecoder.java +++ b/codec/src/main/java/io/netty/handler/codec/FixedLengthFrameDecoder.java @@ -16,9 +16,8 @@ package io.netty.handler.codec; import io.netty.buffer.ByteBuf; -import io.netty.buffer.MessageBuf; import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.ChannelHandlerUtil; +import io.netty.channel.MessageList; /** * A decoder that splits the received {@link ByteBuf}s by the fixed number @@ -39,51 +38,30 @@ import io.netty.channel.ChannelHandlerUtil; public class FixedLengthFrameDecoder extends ByteToMessageDecoder { private final int frameLength; - private final boolean allocateFullBuffer; - - /** - * Calls {@link #FixedLengthFrameDecoder(int, boolean)} with {@code false} - */ - public FixedLengthFrameDecoder(int frameLength) { - this(frameLength, false); - } /** * Creates a new instance. * - * @param frameLength - * the length of the frame - * @param allocateFullBuffer - * {@code true} if the cumulative {@link ByteBuf} should use the - * {@link #frameLength} as its initial size + * @param frameLength the length of the frame */ - public FixedLengthFrameDecoder(int frameLength, boolean allocateFullBuffer) { + public FixedLengthFrameDecoder(int frameLength) { if (frameLength <= 0) { throw new IllegalArgumentException( "frameLength must be a positive integer: " + frameLength); } this.frameLength = frameLength; - this.allocateFullBuffer = allocateFullBuffer; } @Override - public ByteBuf newInboundBuffer(ChannelHandlerContext ctx) throws Exception { - if (allocateFullBuffer) { - return ChannelHandlerUtil.allocate(ctx, frameLength); - } else { - return super.newInboundBuffer(ctx); - } - } - - @Override - protected void decode(ChannelHandlerContext ctx, ByteBuf in, MessageBuf out) throws Exception { + protected void decode(ChannelHandlerContext ctx, ByteBuf in, MessageList out) throws Exception { Object decoded = decode(ctx, in); if (decoded != null) { out.add(decoded); } } - protected Object decode(ChannelHandlerContext ctx, ByteBuf in) throws Exception { + protected Object decode( + @SuppressWarnings("UnusedParameters") ChannelHandlerContext ctx, ByteBuf in) throws Exception { if (in.readableBytes() < frameLength) { return null; } else { diff --git a/codec/src/main/java/io/netty/handler/codec/LengthFieldBasedFrameDecoder.java b/codec/src/main/java/io/netty/handler/codec/LengthFieldBasedFrameDecoder.java index b9a6e357b2..d554eff759 100644 --- a/codec/src/main/java/io/netty/handler/codec/LengthFieldBasedFrameDecoder.java +++ b/codec/src/main/java/io/netty/handler/codec/LengthFieldBasedFrameDecoder.java @@ -16,9 +16,9 @@ package io.netty.handler.codec; import io.netty.buffer.ByteBuf; -import io.netty.buffer.MessageBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.MessageList; import io.netty.handler.codec.serialization.ObjectDecoder; import java.nio.ByteOrder; @@ -348,7 +348,7 @@ public class LengthFieldBasedFrameDecoder extends ByteToMessageDecoder { } @Override - protected void decode(ChannelHandlerContext ctx, ByteBuf in, MessageBuf out) throws Exception { + protected void decode(ChannelHandlerContext ctx, ByteBuf in, MessageList out) throws Exception { Object decoded = decode(ctx, in); if (decoded != null) { out.add(decoded); diff --git a/codec/src/main/java/io/netty/handler/codec/LineBasedFrameDecoder.java b/codec/src/main/java/io/netty/handler/codec/LineBasedFrameDecoder.java index 41153fc25f..414ebb38c0 100644 --- a/codec/src/main/java/io/netty/handler/codec/LineBasedFrameDecoder.java +++ b/codec/src/main/java/io/netty/handler/codec/LineBasedFrameDecoder.java @@ -16,8 +16,8 @@ package io.netty.handler.codec; import io.netty.buffer.ByteBuf; -import io.netty.buffer.MessageBuf; import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.MessageList; /** * A decoder that splits the received {@link ByteBuf}s on line endings. @@ -69,7 +69,7 @@ public class LineBasedFrameDecoder extends ByteToMessageDecoder { } @Override - protected void decode(ChannelHandlerContext ctx, ByteBuf in, MessageBuf out) throws Exception { + protected void decode(ChannelHandlerContext ctx, ByteBuf in, MessageList out) throws Exception { Object decoded = decode(ctx, in); if (decoded != null) { out.add(decoded); diff --git a/codec/src/main/java/io/netty/handler/codec/MessageToByteEncoder.java b/codec/src/main/java/io/netty/handler/codec/MessageToByteEncoder.java index 9aec6d9823..9072105de7 100644 --- a/codec/src/main/java/io/netty/handler/codec/MessageToByteEncoder.java +++ b/codec/src/main/java/io/netty/handler/codec/MessageToByteEncoder.java @@ -16,13 +16,16 @@ package io.netty.handler.codec; import io.netty.buffer.ByteBuf; -import io.netty.buffer.MessageBuf; +import io.netty.buffer.ByteBufUtil; import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.ChannelOutboundMessageHandlerAdapter; +import io.netty.channel.ChannelOutboundHandlerAdapter; +import io.netty.channel.ChannelPromise; +import io.netty.channel.MessageList; +import io.netty.util.internal.TypeParameterMatcher; /** - * {@link ChannelOutboundMessageHandlerAdapter} which encodes message in a stream-like fashion from one message to an + * {@link ChannelOutboundHandlerAdapter} which encodes message in a stream-like fashion from one message to an * {@link ByteBuf}. * * @@ -38,27 +41,73 @@ import io.netty.channel.ChannelOutboundMessageHandlerAdapter; * } * */ -public abstract class MessageToByteEncoder extends ChannelOutboundMessageHandlerAdapter { +public abstract class MessageToByteEncoder extends ChannelOutboundHandlerAdapter { - protected MessageToByteEncoder() { } + private final TypeParameterMatcher matcher; + + protected MessageToByteEncoder() { + matcher = TypeParameterMatcher.find(this, MessageToByteEncoder.class, "I"); + } protected MessageToByteEncoder(Class extends I> outboundMessageType) { - super(outboundMessageType); + matcher = TypeParameterMatcher.get(outboundMessageType); + } + + public boolean acceptOutboundMessage(Object msg) throws Exception { + return matcher.match(msg); } @Override - public void flush(ChannelHandlerContext ctx, I msg) throws Exception { + public void write(ChannelHandlerContext ctx, MessageList msgs, ChannelPromise promise) throws Exception { + MessageList out = MessageList.newInstance(); + boolean success = false; try { - encode(ctx, msg, ctx.nextOutboundByteBuffer()); - } catch (CodecException e) { + ByteBuf buf = null; + int size = msgs.size(); + for (int i = 0; i < size; i ++) { + Object m = msgs.get(i); + if (acceptOutboundMessage(m)) { + @SuppressWarnings("unchecked") + I cast = (I) m; + if (buf == null) { + buf = ctx.alloc().buffer(); + } + try { + encode(ctx, cast, buf); + } finally { + ByteBufUtil.release(cast); + } + } else { + if (buf != null && buf.isReadable()) { + out.add(buf); + buf = null; + } + + out.add(m); + } + } + + if (buf != null && buf.isReadable()) { + out.add(buf); + } + + success = true; + } catch (EncoderException e) { throw e; - } catch (Exception e) { - throw new CodecException(e); + } catch (Throwable e) { + throw new EncoderException(e); + } finally { + msgs.recycle(); + if (success) { + ctx.write(out, promise); + } else { + out.releaseAllAndRecycle(); + } } } /** - * Encode a message into a {@link ByteBuf}. This method will be called till the {@link MessageBuf} has + * Encode a message into a {@link ByteBuf}. This method will be called till the {@link MessageList} has * nothing left. * * @param ctx the {@link ChannelHandlerContext} which this {@link MessageToByteEncoder} belongs to diff --git a/codec/src/main/java/io/netty/handler/codec/MessageToMessageCodec.java b/codec/src/main/java/io/netty/handler/codec/MessageToMessageCodec.java index f2bd26a43b..8f22b7b2e7 100644 --- a/codec/src/main/java/io/netty/handler/codec/MessageToMessageCodec.java +++ b/codec/src/main/java/io/netty/handler/codec/MessageToMessageCodec.java @@ -15,12 +15,10 @@ */ package io.netty.handler.codec; -import io.netty.buffer.MessageBuf; import io.netty.channel.ChannelDuplexHandler; import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.ChannelInboundMessageHandler; -import io.netty.channel.ChannelOutboundMessageHandler; import io.netty.channel.ChannelPromise; +import io.netty.channel.MessageList; import io.netty.util.internal.TypeParameterMatcher; /** @@ -48,13 +46,10 @@ import io.netty.util.internal.TypeParameterMatcher; * } * */ -public abstract class MessageToMessageCodec - extends ChannelDuplexHandler - implements ChannelInboundMessageHandler, - ChannelOutboundMessageHandler { +public abstract class MessageToMessageCodec extends ChannelDuplexHandler { + + private final MessageToMessageEncoder encoder = new MessageToMessageEncoder() { - private final MessageToMessageEncoder encoder = - new MessageToMessageEncoder() { @Override public boolean acceptOutboundMessage(Object msg) throws Exception { return MessageToMessageCodec.this.acceptOutboundMessage(msg); @@ -62,13 +57,12 @@ public abstract class MessageToMessageCodec @Override @SuppressWarnings("unchecked") - protected void encode(ChannelHandlerContext ctx, Object msg, MessageBuf out) throws Exception { + protected void encode(ChannelHandlerContext ctx, Object msg, MessageList
- * public class SquareCodec extends {@link ByteToByteCodec} { - * {@code @Override} - * public void decode({@link ChannelHandlerContext} ctx, {@link ByteBuf} in, {@link ByteBuf} out) - * throws {@link Exception} { - * if (in.readableBytes() < 4) { - * return; - * } - * int value = in.readInt(); - * out.writeInt(value * value); - * } - * - * {@code @Overrride} - * public void encode({@link ChannelHandlerContext} ctx, {@link ByteBuf} in, {@link ByteBuf} out) - * throws {@link Exception} { - * if (in.readableBytes() < 4) { - * return; - * } - * int value = in.readInt(); - * out.writeInt(value / value); - * } - * } - *
- * public class SquareDecoder extends {@link ByteToByteDecoder} { - * {@code @Override} - * public void decode({@link ChannelHandlerContext} ctx, {@link ByteBuf} in, {@link ByteBuf} out) - * throws {@link Exception} { - * if (in.readableBytes() < 4) { - * return; - * } - * int value = in.readInt(); - * out.writeInt(value * value); - * } - * } - *
- * public class SquareEncoder extends {@link ByteToByteEncoder} { - * {@code @Override} - * public void encode({@link ChannelHandlerContext} ctx, {@link ByteBuf} in, {@link ByteBuf} out) - * throws {@link Exception} { - * if (in.readableBytes() < 4) { - * return; - * } - * int value = in.readInt(); - * out.writeInt(value * value); - * } - * } - *
* public class SquareDecoder extends {@link ByteToMessageDecoder} { * {@code @Override} - * public void decode({@link ChannelHandlerContext} ctx, {@link ByteBuf} in, {@link MessageBuf} out) + * public void decode({@link ChannelHandlerContext} ctx, {@link ByteBuf} in, {@link MessageList} out) * throws {@link Exception} { * out.add(in.readBytes(in.readableBytes())); * } * } *