Add a lot of javadocs to make usage more clear
This commit is contained in:
parent
b004066f37
commit
8a7bc2c606
@ -15,6 +15,9 @@
|
|||||||
*/
|
*/
|
||||||
package io.netty.buffer;
|
package io.netty.buffer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A buffer to operate on
|
||||||
|
*/
|
||||||
public interface Buf {
|
public interface Buf {
|
||||||
/**
|
/**
|
||||||
* The BufType which will be handled by the Buf implementation
|
* The BufType which will be handled by the Buf implementation
|
||||||
|
@ -26,6 +26,9 @@ import java.nio.charset.CharsetDecoder;
|
|||||||
import java.nio.charset.CharsetEncoder;
|
import java.nio.charset.CharsetEncoder;
|
||||||
import java.nio.charset.CoderResult;
|
import java.nio.charset.CoderResult;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utility class for operate on a {@link ByteBuf}
|
||||||
|
*/
|
||||||
public final class ByteBufUtil {
|
public final class ByteBufUtil {
|
||||||
|
|
||||||
private static final char[] HEXDUMP_TABLE = new char[256 * 4];
|
private static final char[] HEXDUMP_TABLE = new char[256 * 4];
|
||||||
|
@ -20,30 +20,171 @@ import java.io.OutputStream;
|
|||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A {@link ByteBuf} which is composed out of other {@link ByteBuf}s.
|
||||||
|
*/
|
||||||
public interface CompositeByteBuf extends ByteBuf, Iterable<ByteBuf> {
|
public interface CompositeByteBuf extends ByteBuf, Iterable<ByteBuf> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add the given {@link ByteBuf}.
|
||||||
|
*
|
||||||
|
* @param buffer the {@link ByteBuf} to add
|
||||||
|
* @return self this instance
|
||||||
|
*/
|
||||||
CompositeByteBuf addComponent(ByteBuf buffer);
|
CompositeByteBuf addComponent(ByteBuf buffer);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add the given {@link ByteBuf} on the specific index.
|
||||||
|
*
|
||||||
|
* @param cIndex
|
||||||
|
* the index on which the {@link ByteBuf} will be added
|
||||||
|
* @param buffer
|
||||||
|
* the {@link ByteBuf} to add
|
||||||
|
* @return self
|
||||||
|
* this instance
|
||||||
|
* @thows {@link IndexOutOfBoundsException}
|
||||||
|
* if the index is invalid
|
||||||
|
*/
|
||||||
CompositeByteBuf addComponent(int cIndex, ByteBuf buffer);
|
CompositeByteBuf addComponent(int cIndex, ByteBuf buffer);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add the given {@link ByteBuf}s.
|
||||||
|
*
|
||||||
|
* @param buffers the {@link ByteBuf}s to add
|
||||||
|
* @return self this instance
|
||||||
|
*/
|
||||||
CompositeByteBuf addComponents(ByteBuf... buffers);
|
CompositeByteBuf addComponents(ByteBuf... buffers);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add the given {@link ByteBuf}s.
|
||||||
|
*
|
||||||
|
* @param buffers the {@link ByteBuf}s to add
|
||||||
|
* @return self this instance
|
||||||
|
*/
|
||||||
CompositeByteBuf addComponents(Iterable<ByteBuf> buffers);
|
CompositeByteBuf addComponents(Iterable<ByteBuf> buffers);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add the given {@link ByteBuf}s on the specific index
|
||||||
|
*
|
||||||
|
* @param cIndex
|
||||||
|
* the index on which the {@link ByteBuf} will be added.
|
||||||
|
* @param buffers
|
||||||
|
* the {@link ByteBuf}s to add
|
||||||
|
* @return self
|
||||||
|
* this instance
|
||||||
|
* @thows {@link IndexOutOfBoundsException}
|
||||||
|
* if the index is invalid
|
||||||
|
*
|
||||||
|
*/
|
||||||
CompositeByteBuf addComponents(int cIndex, ByteBuf... buffers);
|
CompositeByteBuf addComponents(int cIndex, ByteBuf... buffers);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add the given {@link ByteBuf}s on the specific index
|
||||||
|
*
|
||||||
|
* @param cIndex
|
||||||
|
* the index on which the {@link ByteBuf} will be added.
|
||||||
|
* @param buffers
|
||||||
|
* the {@link ByteBuf}s to add
|
||||||
|
* @return self
|
||||||
|
* this instance
|
||||||
|
* @thows {@link IndexOutOfBoundsException}
|
||||||
|
* if the index is invalid
|
||||||
|
*/
|
||||||
CompositeByteBuf addComponents(int cIndex, Iterable<ByteBuf> buffers);
|
CompositeByteBuf addComponents(int cIndex, Iterable<ByteBuf> buffers);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the {@link ByteBuf} from the given index.
|
||||||
|
*
|
||||||
|
* @param cIndex
|
||||||
|
* the index on from which the {@link ByteBuf} will be remove
|
||||||
|
* @return self
|
||||||
|
* this instance
|
||||||
|
* @thows {@link IndexOutOfBoundsException}
|
||||||
|
* if the index is invalid
|
||||||
|
*/
|
||||||
CompositeByteBuf removeComponent(int cIndex);
|
CompositeByteBuf removeComponent(int cIndex);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the number of {@link ByteBuf}s starting from the given index.
|
||||||
|
*
|
||||||
|
* @param cIndex
|
||||||
|
* the index on which the {@link ByteBuf}s will be started to removed
|
||||||
|
* @param numComponents
|
||||||
|
* the number of components to remove
|
||||||
|
* @return self
|
||||||
|
* this instance
|
||||||
|
* @thows {@link IndexOutOfBoundsException}
|
||||||
|
* if the index is invalid
|
||||||
|
*/
|
||||||
CompositeByteBuf removeComponents(int cIndex, int numComponents);
|
CompositeByteBuf removeComponents(int cIndex, int numComponents);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the current number of {@link ByteBuf}'s that are composed in this instance
|
||||||
|
*/
|
||||||
int numComponents();
|
int numComponents();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the max number of {@link ByteBuf}'s that are composed in this instance
|
||||||
|
*/
|
||||||
int maxNumComponents();
|
int maxNumComponents();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the {@link ByteBuf} on the specified index
|
||||||
|
*
|
||||||
|
* @param cIndex
|
||||||
|
* the index for which the {@link ByteBuf} should be returned
|
||||||
|
* @return buf
|
||||||
|
* the {@link ByteBuf} on the specified index
|
||||||
|
* @thows {@link IndexOutOfBoundsException}
|
||||||
|
* if the index is invalid
|
||||||
|
*/
|
||||||
ByteBuf component(int cIndex);
|
ByteBuf component(int cIndex);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the {@link ByteBuf} on the specified index
|
||||||
|
*
|
||||||
|
* @param offset
|
||||||
|
* the offset for which the {@link ByteBuf} should be returned
|
||||||
|
* @return buf
|
||||||
|
* the {@link ByteBuf} on the specified index
|
||||||
|
* @thows {@link IndexOutOfBoundsException}
|
||||||
|
* if the offset is invalid
|
||||||
|
*/
|
||||||
ByteBuf componentAtOffset(int offset);
|
ByteBuf componentAtOffset(int offset);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Discard all {@link ByteBuf}s which are read.
|
||||||
|
*
|
||||||
|
* @return self this instance
|
||||||
|
*/
|
||||||
CompositeByteBuf discardReadComponents();
|
CompositeByteBuf discardReadComponents();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Consolidate the composed {@link ByteBuf}s
|
||||||
|
*
|
||||||
|
* @return self this instance
|
||||||
|
*/
|
||||||
CompositeByteBuf consolidate();
|
CompositeByteBuf consolidate();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Consolidate the composed {@link ByteBuf}s
|
||||||
|
*
|
||||||
|
* @param cIndex
|
||||||
|
* the index on which to start to compose
|
||||||
|
* @param numComponents
|
||||||
|
* the number of components to compose
|
||||||
|
* @return self
|
||||||
|
* this instance
|
||||||
|
* @thows {@link IndexOutOfBoundsException}
|
||||||
|
* if the offset is invalid
|
||||||
|
*/
|
||||||
CompositeByteBuf consolidate(int cIndex, int numComponents);
|
CompositeByteBuf consolidate(int cIndex, int numComponents);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the index for the given offset
|
||||||
|
*/
|
||||||
int toComponentIndex(int offset);
|
int toComponentIndex(int offset);
|
||||||
|
|
||||||
int toByteIndex(int cIndex);
|
int toByteIndex(int cIndex);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -19,6 +19,10 @@ import java.util.ArrayDeque;
|
|||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default {@link MessageBuf} implementation
|
||||||
|
*
|
||||||
|
*/
|
||||||
final class DefaultMessageBuf<T> extends ArrayDeque<T> implements MessageBuf<T> {
|
final class DefaultMessageBuf<T> extends ArrayDeque<T> implements MessageBuf<T> {
|
||||||
|
|
||||||
private static final long serialVersionUID = 1229808623624907552L;
|
private static final long serialVersionUID = 1229808623624907552L;
|
||||||
|
@ -19,11 +19,26 @@ import java.util.Collection;
|
|||||||
import java.util.Queue;
|
import java.util.Queue;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Buf which operates on messages
|
* Buf which operates on messages.
|
||||||
*
|
*
|
||||||
* @param <T>
|
* @param <T> the type of the messages that are hold by this {@link MessageBuf}
|
||||||
*/
|
*/
|
||||||
public interface MessageBuf<T> extends Buf, Queue<T> {
|
public interface MessageBuf<T> extends Buf, Queue<T> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Drain the content of te {@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);
|
int drainTo(Collection<? super T> c);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Drain the content of te {@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);
|
int drainTo(Collection<? super T> c, int maxElements);
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,36 @@ import io.netty.channel.ChannelHandlerContext;
|
|||||||
import io.netty.channel.ChannelInboundByteHandler;
|
import io.netty.channel.ChannelInboundByteHandler;
|
||||||
import io.netty.channel.ChannelOutboundByteHandler;
|
import io.netty.channel.ChannelOutboundByteHandler;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A Codec for on-the-fly encoding/decoding of bytes.
|
||||||
|
*
|
||||||
|
* This can be though of an 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}.
|
||||||
|
* <pre>
|
||||||
|
* 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);
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
public abstract class ByteToByteCodec
|
public abstract class ByteToByteCodec
|
||||||
extends ChannelHandlerAdapter
|
extends ChannelHandlerAdapter
|
||||||
implements ChannelInboundByteHandler, ChannelOutboundByteHandler {
|
implements ChannelInboundByteHandler, ChannelOutboundByteHandler {
|
||||||
@ -76,10 +106,16 @@ public abstract class ByteToByteCodec
|
|||||||
encoder.freeOutboundBuffer(ctx, buf);
|
encoder.freeOutboundBuffer(ctx, buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see {@link ByteToByteEncoder#encode(ChannelHandlerContext, ByteBuf, ByteBuf)}
|
||||||
|
*/
|
||||||
public abstract void encode(
|
public abstract void encode(
|
||||||
ChannelHandlerContext ctx,
|
ChannelHandlerContext ctx,
|
||||||
ByteBuf in, ByteBuf out) throws Exception;
|
ByteBuf in, ByteBuf out) throws Exception;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see {@link ByteToByteDecoder#decode(ChannelHandlerContext, ByteBuf, ByteBuf)}
|
||||||
|
*/
|
||||||
public abstract void decode(
|
public abstract void decode(
|
||||||
ChannelHandlerContext ctx,
|
ChannelHandlerContext ctx,
|
||||||
ByteBuf in, ByteBuf out) throws Exception;
|
ByteBuf in, ByteBuf out) throws Exception;
|
||||||
|
@ -19,6 +19,29 @@ import io.netty.buffer.ByteBuf;
|
|||||||
import io.netty.channel.ChannelHandlerContext;
|
import io.netty.channel.ChannelHandlerContext;
|
||||||
import io.netty.channel.ChannelInboundByteHandlerAdapter;
|
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}.
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* 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);
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
public abstract class ByteToByteDecoder extends ChannelInboundByteHandlerAdapter {
|
public abstract class ByteToByteDecoder extends ChannelInboundByteHandlerAdapter {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -52,6 +75,9 @@ public abstract class ByteToByteDecoder extends ChannelInboundByteHandlerAdapter
|
|||||||
ctx.fireChannelInactive();
|
ctx.fireChannelInactive();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call the {@link #decode(ChannelHandlerContext, ByteBuf, ByteBuf)} method until it is done.
|
||||||
|
*/
|
||||||
private void callDecode(ChannelHandlerContext ctx, ByteBuf in, ByteBuf out) {
|
private void callDecode(ChannelHandlerContext ctx, ByteBuf in, ByteBuf out) {
|
||||||
int oldOutSize = out.readableBytes();
|
int oldOutSize = out.readableBytes();
|
||||||
while (in.readable()) {
|
while (in.readable()) {
|
||||||
@ -76,8 +102,24 @@ public abstract class ByteToByteDecoder extends ChannelInboundByteHandlerAdapter
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
public abstract void decode(ChannelHandlerContext ctx, ByteBuf in, ByteBuf out) throws Exception;
|
public 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.
|
||||||
|
*/
|
||||||
public void decodeLast(ChannelHandlerContext ctx, ByteBuf in, ByteBuf out) throws Exception {
|
public void decodeLast(ChannelHandlerContext ctx, ByteBuf in, ByteBuf out) throws Exception {
|
||||||
decode(ctx, in, out);
|
decode(ctx, in, out);
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,29 @@ import io.netty.channel.ChannelFuture;
|
|||||||
import io.netty.channel.ChannelHandlerContext;
|
import io.netty.channel.ChannelHandlerContext;
|
||||||
import io.netty.channel.ChannelOutboundByteHandlerAdapter;
|
import io.netty.channel.ChannelOutboundByteHandlerAdapter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@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}.
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* 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);
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
public abstract class ByteToByteEncoder extends ChannelOutboundByteHandlerAdapter {
|
public abstract class ByteToByteEncoder extends ChannelOutboundByteHandlerAdapter {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -47,5 +70,14 @@ public abstract class ByteToByteEncoder extends ChannelOutboundByteHandlerAdapte
|
|||||||
ctx.flush(future);
|
ctx.flush(future);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
public abstract void encode(ChannelHandlerContext ctx, ByteBuf in, ByteBuf out) throws Exception;
|
public abstract void encode(ChannelHandlerContext ctx, ByteBuf in, ByteBuf out) throws Exception;
|
||||||
}
|
}
|
||||||
|
@ -22,6 +22,23 @@ import io.netty.channel.ChannelInboundByteHandler;
|
|||||||
import io.netty.channel.ChannelInboundHandlerAdapter;
|
import io.netty.channel.ChannelInboundHandlerAdapter;
|
||||||
import io.netty.channel.ChannelPipeline;
|
import io.netty.channel.ChannelPipeline;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link ChannelInboundByteHandler} 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}.
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* public class SquareDecoder extends {@link ByteToMessageDecoder}<{@link ByteBuf}> {
|
||||||
|
* {@code @Override}
|
||||||
|
* public {@link ByteBuf} decode({@link ChannelHandlerContext} ctx, {@link ByteBuf} in)
|
||||||
|
* throws {@link Exception} {
|
||||||
|
* return in.readBytes(in.readableBytes());
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
public abstract class ByteToMessageDecoder<O>
|
public abstract class ByteToMessageDecoder<O>
|
||||||
extends ChannelInboundHandlerAdapter implements ChannelInboundByteHandler {
|
extends ChannelInboundHandlerAdapter implements ChannelInboundByteHandler {
|
||||||
|
|
||||||
@ -138,8 +155,26 @@ public abstract class ByteToMessageDecoder<O>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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, 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 in the {@link ByteBuf} from which to read data
|
||||||
|
* @return message the message to which the content of the {@link ByteBuf} was decoded, or {@code null} if
|
||||||
|
* there was not enough data left in the {@link ByteBuf} to decode.
|
||||||
|
* @throws Exception is thrown if an error accour
|
||||||
|
*/
|
||||||
public abstract O decode(ChannelHandlerContext ctx, ByteBuf in) throws Exception;
|
public abstract O decode(ChannelHandlerContext ctx, ByteBuf in) 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)} but sub-classes may
|
||||||
|
* override this for some special cleanup operation.
|
||||||
|
*/
|
||||||
public O decodeLast(ChannelHandlerContext ctx, ByteBuf in) throws Exception {
|
public O decodeLast(ChannelHandlerContext ctx, ByteBuf in) throws Exception {
|
||||||
return decode(ctx, in);
|
return decode(ctx, in);
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
package io.netty.handler.codec;
|
package io.netty.handler.codec;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An {@link Exception} which is thrown when the received frame data could not be decoded by
|
* An {@link DecoderException} which is thrown when the received frame data could not be decoded by
|
||||||
* an inbound handler.
|
* an inbound handler.
|
||||||
*
|
*
|
||||||
* @apiviz.exclude
|
* @apiviz.exclude
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
package io.netty.handler.codec;
|
package io.netty.handler.codec;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An {@link Exception} which is thrown by an encoder.
|
* An {@link CodecException} which is thrown by a dencoder.
|
||||||
*
|
*
|
||||||
* @apiviz.exclude
|
* @apiviz.exclude
|
||||||
*/
|
*/
|
||||||
|
@ -39,7 +39,7 @@ import io.netty.channel.ChannelHandlerContext;
|
|||||||
* | ABC\nDEF\r\n |
|
* | ABC\nDEF\r\n |
|
||||||
* +--------------+
|
* +--------------+
|
||||||
* </pre>
|
* </pre>
|
||||||
* a {@link DelimiterBasedFrameDecoder}{@code (}{@link Delimiters#lineDelimiter() Delimiters.lineDelimiter()}{@code )}
|
* a {@link DelimiterBasedFrameDecoder}({@link Delimiters#lineDelimiter() Delimiters.lineDelimiter()})
|
||||||
* will choose {@code '\n'} as the first delimiter and produce two frames:
|
* will choose {@code '\n'} as the first delimiter and produce two frames:
|
||||||
* <pre>
|
* <pre>
|
||||||
* +-----+-----+
|
* +-----+-----+
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
package io.netty.handler.codec;
|
package io.netty.handler.codec;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An {@link Exception} which is thrown by an encoder.
|
* An {@link CodecException} which is thrown by an encoder.
|
||||||
*
|
*
|
||||||
* @apiviz.exclude
|
* @apiviz.exclude
|
||||||
*/
|
*/
|
||||||
|
@ -411,14 +411,10 @@ public class LengthFieldBasedFrameDecoder extends ByteToMessageDecoder<Object> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extract the sub-region of the specified buffer. This method is called by
|
* Extract the sub-region of the specified buffer.
|
||||||
* {@link #decode(ChannelInboundHandlerContext, ByteBuf)} for each
|
|
||||||
* frame. The default implementation returns a copy of the sub-region.
|
|
||||||
* For example, you could override this method to use an alternative
|
|
||||||
* {@link ByteBufFactory}.
|
|
||||||
* <p>
|
* <p>
|
||||||
* If you are sure that the frame and its content are not accessed after
|
* If you are sure that the frame and its content are not accessed after
|
||||||
* the current {@link #decode(ChannelInboundHandlerContext, ByteBuf)}
|
* the current {@link #decode(ChannelHandlerContext, ByteBuf)}
|
||||||
* call returns, you can even avoid memory copy by returning the sliced
|
* call returns, you can even avoid memory copy by returning the sliced
|
||||||
* sub-region (i.e. <tt>return buffer.slice(index, length)</tt>).
|
* sub-region (i.e. <tt>return buffer.slice(index, length)</tt>).
|
||||||
* It's often useful when you convert the extracted frame into an object.
|
* It's often useful when you convert the extracted frame into an object.
|
||||||
|
@ -19,13 +19,10 @@ import io.netty.buffer.ByteBuf;
|
|||||||
import io.netty.channel.ChannelHandler.Sharable;
|
import io.netty.channel.ChannelHandler.Sharable;
|
||||||
import io.netty.channel.ChannelHandlerContext;
|
import io.netty.channel.ChannelHandlerContext;
|
||||||
|
|
||||||
import java.nio.ByteOrder;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An encoder that prepends the length of the message. The length value is
|
* An encoder that prepends the length of the message. The length value is
|
||||||
* prepended as a binary form. It is encoded in either big endian or little
|
* prepended as a binary form.
|
||||||
* endian depending on the default {@link ByteOrder} of the current
|
|
||||||
* {@link ByteBufFactory}.
|
|
||||||
* <p>
|
* <p>
|
||||||
* For example, <tt>{@link LengthFieldPrepender}(2)</tt> will encode the
|
* For example, <tt>{@link LengthFieldPrepender}(2)</tt> will encode the
|
||||||
* following 12-bytes string:
|
* following 12-bytes string:
|
||||||
|
@ -22,6 +22,24 @@ import io.netty.channel.ChannelHandlerContext;
|
|||||||
import io.netty.channel.ChannelOutboundMessageHandlerAdapter;
|
import io.netty.channel.ChannelOutboundMessageHandlerAdapter;
|
||||||
import io.netty.channel.ChannelHandlerUtil;
|
import io.netty.channel.ChannelHandlerUtil;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link ChannelOutboundMessageHandlerAdapter} which encodes message in a stream-like fashion from one message to an
|
||||||
|
* {@link ByteBuf}.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Example implementation which encodes {@link Integer}s to a {@link ByteBuf}.
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* public class IntegerEncoder extends {@link MessageToByteEncoder}<{@link Integer}> {
|
||||||
|
* {@code @Override}
|
||||||
|
* public void encode({@link ChannelHandlerContext} ctx, {@link Integer} msg, {@link ByteBuf} out)
|
||||||
|
* throws {@link Exception} {
|
||||||
|
* out.writeInt(msg);
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
public abstract class MessageToByteEncoder<I> extends ChannelOutboundMessageHandlerAdapter<I> {
|
public abstract class MessageToByteEncoder<I> extends ChannelOutboundMessageHandlerAdapter<I> {
|
||||||
|
|
||||||
private final Class<?>[] acceptedMsgTypes;
|
private final Class<?>[] acceptedMsgTypes;
|
||||||
@ -71,5 +89,14 @@ public abstract class MessageToByteEncoder<I> extends ChannelOutboundMessageHand
|
|||||||
return ChannelHandlerUtil.acceptMessage(acceptedMsgTypes, msg);
|
return ChannelHandlerUtil.acceptMessage(acceptedMsgTypes, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encode a message into a {@link ByteBuf}. This method will be called till the {@link MessageBuf} has
|
||||||
|
* nothing left.
|
||||||
|
*
|
||||||
|
* @param ctx the {@link ChannelHandlerContext} which this {@link MessageToByteEncoder} belongs to
|
||||||
|
* @param msg the message to encode
|
||||||
|
* @param out the {@link ByteBuf} into which the encoded message will be written
|
||||||
|
* @throws Exception is thrown if an error accour
|
||||||
|
*/
|
||||||
public abstract void encode(ChannelHandlerContext ctx, I msg, ByteBuf out) throws Exception;
|
public abstract void encode(ChannelHandlerContext ctx, I msg, ByteBuf out) throws Exception;
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,30 @@ import io.netty.channel.ChannelHandlerUtil;
|
|||||||
import io.netty.channel.ChannelInboundMessageHandler;
|
import io.netty.channel.ChannelInboundMessageHandler;
|
||||||
import io.netty.channel.ChannelOutboundMessageHandler;
|
import io.netty.channel.ChannelOutboundMessageHandler;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A Codec for on-the-fly encoding/decoding of message.
|
||||||
|
*
|
||||||
|
* This can be though of an combination of {@link MessageToMessageDecoder} and {@link MessageToMessageEncoder}.
|
||||||
|
*
|
||||||
|
* Here is an example of a {@link MessageToMessageCodec} which just decode from {@link Integer} to {@link Long}
|
||||||
|
* and encode from {@link Long} to {@link Integer}.
|
||||||
|
* <pre>
|
||||||
|
* public class NumberCodec extends
|
||||||
|
* {@link MessageToMessageCodec}<{@link Integer}, {@link Long}, {@link Long}, {@link Integer}> {
|
||||||
|
* {@code @Override}
|
||||||
|
* public {@link Long} decode({@link ChannelHandlerContext} ctx, {@link Integer} msg)
|
||||||
|
* throws {@link Exception} {
|
||||||
|
* return msg.longValue();
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* {@code @Overrride}
|
||||||
|
* public {@link Integer} encode({@link ChannelHandlerContext} ctx, {@link Long} msg)
|
||||||
|
* throws {@link Exception} {
|
||||||
|
* return msg.intValue();
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
public abstract class MessageToMessageCodec<INBOUND_IN, INBOUND_OUT, OUTBOUND_IN, OUTBOUND_OUT>
|
public abstract class MessageToMessageCodec<INBOUND_IN, INBOUND_OUT, OUTBOUND_IN, OUTBOUND_OUT>
|
||||||
extends ChannelHandlerAdapter
|
extends ChannelHandlerAdapter
|
||||||
implements ChannelInboundMessageHandler<INBOUND_IN>,
|
implements ChannelInboundMessageHandler<INBOUND_IN>,
|
||||||
|
@ -21,12 +21,38 @@ import io.netty.channel.ChannelHandlerContext;
|
|||||||
import io.netty.channel.ChannelHandlerUtil;
|
import io.netty.channel.ChannelHandlerUtil;
|
||||||
import io.netty.channel.ChannelInboundHandlerAdapter;
|
import io.netty.channel.ChannelInboundHandlerAdapter;
|
||||||
import io.netty.channel.ChannelInboundMessageHandler;
|
import io.netty.channel.ChannelInboundMessageHandler;
|
||||||
|
import io.netty.channel.ChannelPipeline;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link ChannelInboundMessageHandler} which decodes from one message to an other message
|
||||||
|
*
|
||||||
|
* For example here is an implementation which decodes a {@link String} to an {@link Integer} which represent
|
||||||
|
* the length of the {@link String}.
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* public class StringToIntegerDecoder extends
|
||||||
|
* {@link MessageToMessageDecoder}<{@link String},{@link Integer}> {
|
||||||
|
* public StringToIntegerDecoder() {
|
||||||
|
* super(String.class);
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* {@code @Override}
|
||||||
|
* public {@link Integer} decode({@link ChannelHandlerContext} ctx, {@link String} message)
|
||||||
|
* throws {@link Exception} {
|
||||||
|
* return message.length());
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
public abstract class MessageToMessageDecoder<I, O>
|
public abstract class MessageToMessageDecoder<I, O>
|
||||||
extends ChannelInboundHandlerAdapter implements ChannelInboundMessageHandler<I> {
|
extends ChannelInboundHandlerAdapter implements ChannelInboundMessageHandler<I> {
|
||||||
|
|
||||||
private final Class<?>[] acceptedMsgTypes;
|
private final Class<?>[] acceptedMsgTypes;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The types which will be accepted by the decoder. If a received message is an other type it will be just forwared
|
||||||
|
* to the next {@link ChannelInboundMessageHandler} in the {@link ChannelPipeline}
|
||||||
|
*/
|
||||||
protected MessageToMessageDecoder(Class<?>... acceptedMsgTypes) {
|
protected MessageToMessageDecoder(Class<?>... acceptedMsgTypes) {
|
||||||
this.acceptedMsgTypes = ChannelHandlerUtil.acceptedMessageTypes(acceptedMsgTypes);
|
this.acceptedMsgTypes = ChannelHandlerUtil.acceptedMessageTypes(acceptedMsgTypes);
|
||||||
}
|
}
|
||||||
@ -80,12 +106,20 @@ public abstract class MessageToMessageDecoder<I, O>
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns {@code true} if and only if the specified message can be decoded by this decoder.
|
* Returns {@code true} if and only if the specified message can be decoded by this decoder.
|
||||||
*
|
|
||||||
* @param msg the message
|
|
||||||
*/
|
*/
|
||||||
public boolean isDecodable(Object msg) throws Exception {
|
public boolean isDecodable(Object msg) throws Exception {
|
||||||
return ChannelHandlerUtil.acceptMessage(acceptedMsgTypes, msg);
|
return ChannelHandlerUtil.acceptMessage(acceptedMsgTypes, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decode from one message to an other. This method will be called till either the {@link MessageBuf} has
|
||||||
|
* nothing left or till this method returns {@code null}.
|
||||||
|
*
|
||||||
|
* @param ctx the {@link ChannelHandlerContext} which this {@link MessageToMessageDecoder} belongs to
|
||||||
|
* @param msg the message to decode to an other one
|
||||||
|
* @return message the decoded message or {@code null} if more messages are needed be cause the implementation
|
||||||
|
* needs to do some kind of aggragation
|
||||||
|
* @throws Exception is thrown if an error accour
|
||||||
|
*/
|
||||||
public abstract O decode(ChannelHandlerContext ctx, I msg) throws Exception;
|
public abstract O decode(ChannelHandlerContext ctx, I msg) throws Exception;
|
||||||
}
|
}
|
||||||
|
@ -18,13 +18,39 @@ package io.netty.handler.codec;
|
|||||||
import io.netty.buffer.MessageBuf;
|
import io.netty.buffer.MessageBuf;
|
||||||
import io.netty.channel.ChannelFuture;
|
import io.netty.channel.ChannelFuture;
|
||||||
import io.netty.channel.ChannelHandlerContext;
|
import io.netty.channel.ChannelHandlerContext;
|
||||||
|
import io.netty.channel.ChannelOutboundMessageHandler;
|
||||||
import io.netty.channel.ChannelOutboundMessageHandlerAdapter;
|
import io.netty.channel.ChannelOutboundMessageHandlerAdapter;
|
||||||
import io.netty.channel.ChannelHandlerUtil;
|
import io.netty.channel.ChannelHandlerUtil;
|
||||||
|
import io.netty.channel.ChannelPipeline;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link ChannelOutboundMessageHandlerAdapter} which encodes from one message to an other message
|
||||||
|
*
|
||||||
|
* For example here is an implementation which decodes an {@link Integer} to an {@link String}.
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* public class IntegerToStringEncoder extends
|
||||||
|
* {@link MessageToMessageEncoder}<{@link Integer},{@link String}> {
|
||||||
|
* public StringToIntegerDecoder() {
|
||||||
|
* super(String.class);
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* {@code @Override}
|
||||||
|
* public {@link String} encode({@link ChannelHandlerContext} ctx, {@link Integer} message)
|
||||||
|
* throws {@link Exception} {
|
||||||
|
* return message.toString();
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
public abstract class MessageToMessageEncoder<I, O> extends ChannelOutboundMessageHandlerAdapter<I> {
|
public abstract class MessageToMessageEncoder<I, O> extends ChannelOutboundMessageHandlerAdapter<I> {
|
||||||
|
|
||||||
private final Class<?>[] acceptedMsgTypes;
|
private final Class<?>[] acceptedMsgTypes;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The types which will be accepted by the decoder. If a received message is an other type it will be just forwared
|
||||||
|
* to the next {@link ChannelOutboundMessageHandler} in the {@link ChannelPipeline}
|
||||||
|
*/
|
||||||
protected MessageToMessageEncoder(Class<?>... acceptedMsgTypes) {
|
protected MessageToMessageEncoder(Class<?>... acceptedMsgTypes) {
|
||||||
this.acceptedMsgTypes = ChannelHandlerUtil.acceptedMessageTypes(acceptedMsgTypes);
|
this.acceptedMsgTypes = ChannelHandlerUtil.acceptedMessageTypes(acceptedMsgTypes);
|
||||||
}
|
}
|
||||||
@ -75,5 +101,15 @@ public abstract class MessageToMessageEncoder<I, O> extends ChannelOutboundMessa
|
|||||||
return ChannelHandlerUtil.acceptMessage(acceptedMsgTypes, msg);
|
return ChannelHandlerUtil.acceptMessage(acceptedMsgTypes, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encode from one message to an other. This method will be called till either the {@link MessageBuf} has nothing
|
||||||
|
* left or till this method returns {@code null}.
|
||||||
|
*
|
||||||
|
* @param ctx the {@link ChannelHandlerContext} which this {@link MessageToMessageEncoder} belongs to
|
||||||
|
* @param msg the message to encode to an other one
|
||||||
|
* @return message the encoded message or {@code null} if more messages are needed be cause the implementation
|
||||||
|
* needs to do some kind of aggragation
|
||||||
|
* @throws Exception is thrown if an error accour
|
||||||
|
*/
|
||||||
public abstract O encode(ChannelHandlerContext ctx, I msg) throws Exception;
|
public abstract O encode(ChannelHandlerContext ctx, I msg) throws Exception;
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,6 @@
|
|||||||
package io.netty.handler.codec;
|
package io.netty.handler.codec;
|
||||||
|
|
||||||
import io.netty.buffer.ByteBuf;
|
import io.netty.buffer.ByteBuf;
|
||||||
import io.netty.channel.Channel;
|
|
||||||
import io.netty.channel.ChannelHandler;
|
import io.netty.channel.ChannelHandler;
|
||||||
import io.netty.channel.ChannelHandlerContext;
|
import io.netty.channel.ChannelHandlerContext;
|
||||||
import io.netty.channel.ChannelHandlerUtil;
|
import io.netty.channel.ChannelHandlerUtil;
|
||||||
@ -28,44 +27,41 @@ import io.netty.util.internal.Signal;
|
|||||||
* of a non-blocking decoder in the blocking I/O paradigm.
|
* of a non-blocking decoder in the blocking I/O paradigm.
|
||||||
* <p>
|
* <p>
|
||||||
* The biggest difference between {@link ReplayingDecoder} and
|
* The biggest difference between {@link ReplayingDecoder} and
|
||||||
* {@link FrameDecoder} is that {@link ReplayingDecoder} allows you to
|
* {@link ByteToMessageDecoder} is that {@link ReplayingDecoder} allows you to
|
||||||
* implement the {@code decode()} and {@code decodeLast()} methods just like
|
* implement the {@code decode()} and {@code decodeLast()} methods just like
|
||||||
* all required bytes were received already, rather than checking the
|
* all required bytes were received already, rather than checking the
|
||||||
* availability of the required bytes. For example, the following
|
* availability of the required bytes. For example, the following
|
||||||
* {@link FrameDecoder} implementation:
|
* {@link ByteToByteDecoder} implementation:
|
||||||
* <pre>
|
* <pre>
|
||||||
* public class IntegerHeaderFrameDecoder extends {@link FrameDecoder} {
|
* public class IntegerHeaderFrameDecoder extends {@link ByteToMessageDecoder}<{@link ByteBuf}> {
|
||||||
*
|
*
|
||||||
* {@code @Override}
|
* {@code @Override}
|
||||||
* protected Object decode({@link ChannelHandlerContext} ctx,
|
* protected ByteBuf decode({@link ChannelHandlerContext} ctx,
|
||||||
* {@link Channel} channel,
|
* {@link ByteBuf} in) throws Exception {
|
||||||
* {@link ByteBuf} buf) throws Exception {
|
|
||||||
*
|
*
|
||||||
* if (buf.readableBytes() < 4) {
|
* if (in.readableBytes() < 4) {
|
||||||
* return <strong>null</strong>;
|
* return <strong>null</strong>;
|
||||||
* }
|
* }
|
||||||
*
|
*
|
||||||
* buf.markReaderIndex();
|
* in.markReaderIndex();
|
||||||
* int length = buf.readInt();
|
* int length = in.readInt();
|
||||||
*
|
*
|
||||||
* if (buf.readableBytes() < length) {
|
* if (in.readableBytes() < length) {
|
||||||
* buf.resetReaderIndex();
|
* in.resetReaderIndex();
|
||||||
* return <strong>null</strong>;
|
* return <strong>null</strong>;
|
||||||
* }
|
* }
|
||||||
*
|
*
|
||||||
* return buf.readBytes(length);
|
* return in.readBytes(length);
|
||||||
* }
|
* }
|
||||||
* }
|
* }
|
||||||
* </pre>
|
* </pre>
|
||||||
* is simplified like the following with {@link ReplayingDecoder}:
|
* is simplified like the following with {@link ReplayingDecoder}:
|
||||||
* <pre>
|
* <pre>
|
||||||
* public class IntegerHeaderFrameDecoder
|
* public class IntegerHeaderFrameDecoder
|
||||||
* extends {@link ReplayingDecoder}<{@link VoidEnum}> {
|
* extends {@link ReplayingDecoder}<{@link ByteBuf},{@link Void}> {
|
||||||
*
|
*
|
||||||
* protected Object decode({@link ChannelHandlerContext} ctx,
|
* protected Object decode({@link ChannelHandlerContext} ctx,
|
||||||
* {@link Channel} channel,
|
* {@link ByteBuf} buf) throws Exception {
|
||||||
* {@link ByteBuf} buf,
|
|
||||||
* {@link VoidEnum} state) throws Exception {
|
|
||||||
*
|
*
|
||||||
* return buf.readBytes(buf.readInt());
|
* return buf.readBytes(buf.readInt());
|
||||||
* }
|
* }
|
||||||
@ -104,12 +100,12 @@ import io.netty.util.internal.Signal;
|
|||||||
* <li>You must keep in mind that {@code decode(..)} method can be called many
|
* <li>You must keep in mind that {@code decode(..)} method can be called many
|
||||||
* times to decode a single message. For example, the following code will
|
* times to decode a single message. For example, the following code will
|
||||||
* not work:
|
* not work:
|
||||||
* <pre> public class MyDecoder extends {@link ReplayingDecoder}<{@link Void}> {
|
* <pre> public class MyDecoder extends {@link ReplayingDecoder}<{@link Integer}, {@link Void}> {
|
||||||
*
|
*
|
||||||
* private final Queue<Integer> values = new LinkedList<Integer>();
|
* private final Queue<Integer> values = new LinkedList<Integer>();
|
||||||
*
|
*
|
||||||
* {@code @Override}
|
* {@code @Override}
|
||||||
* public Object decode(.., {@link ByteBuf} buffer, ..) throws Exception {
|
* public {@link Integer} decode(.., {@link ByteBuf} in) throws Exception {
|
||||||
*
|
*
|
||||||
* // A message contains 2 integers.
|
* // A message contains 2 integers.
|
||||||
* values.offer(buffer.readInt());
|
* values.offer(buffer.readInt());
|
||||||
@ -124,12 +120,12 @@ import io.netty.util.internal.Signal;
|
|||||||
* The correct implementation looks like the following, and you can also
|
* The correct implementation looks like the following, and you can also
|
||||||
* utilize the 'checkpoint' feature which is explained in detail in the
|
* utilize the 'checkpoint' feature which is explained in detail in the
|
||||||
* next section.
|
* next section.
|
||||||
* <pre> public class MyDecoder extends {@link ReplayingDecoder}<{@link Void}> {
|
* <pre> public class MyDecoder extends {@link ReplayingDecoder}<{@link Integer}, {@link Void}> {
|
||||||
*
|
*
|
||||||
* private final Queue<Integer> values = new LinkedList<Integer>();
|
* private final Queue<Integer> values = new LinkedList<Integer>();
|
||||||
*
|
*
|
||||||
* {@code @Override}
|
* {@code @Override}
|
||||||
* public Object decode(.., {@link ByteBuf} buffer, ..) throws Exception {
|
* public {@link Integer} decode(.., {@link ByteBuf} buffer) throws Exception {
|
||||||
*
|
*
|
||||||
* // Revert the state of the variable that might have been changed
|
* // Revert the state of the variable that might have been changed
|
||||||
* // since the last partial decode.
|
* // since the last partial decode.
|
||||||
@ -171,7 +167,7 @@ import io.netty.util.internal.Signal;
|
|||||||
* }
|
* }
|
||||||
*
|
*
|
||||||
* public class IntegerHeaderFrameDecoder
|
* public class IntegerHeaderFrameDecoder
|
||||||
* extends {@link ReplayingDecoder}<<strong>MyDecoderState</strong>> {
|
* extends {@link ReplayingDecoder}<{@link ByteBuf}, <strong>MyDecoderState</strong>> {
|
||||||
*
|
*
|
||||||
* private int length;
|
* private int length;
|
||||||
*
|
*
|
||||||
@ -181,16 +177,14 @@ import io.netty.util.internal.Signal;
|
|||||||
* }
|
* }
|
||||||
*
|
*
|
||||||
* {@code @Override}
|
* {@code @Override}
|
||||||
* protected Object decode({@link ChannelHandlerContext} ctx,
|
* protected {@link ByteBuf} decode({@link ChannelHandlerContext} ctx,
|
||||||
* {@link Channel} channel,
|
* {@link ByteBuf} in) throws Exception {
|
||||||
* {@link ByteBuf} buf,
|
* switch (state()) {
|
||||||
* <b>MyDecoderState</b> state) throws Exception {
|
|
||||||
* switch (state) {
|
|
||||||
* case READ_LENGTH:
|
* case READ_LENGTH:
|
||||||
* length = buf.readInt();
|
* length = buf.readInt();
|
||||||
* <strong>checkpoint(MyDecoderState.READ_CONTENT);</strong>
|
* <strong>checkpoint(MyDecoderState.READ_CONTENT);</strong>
|
||||||
* case READ_CONTENT:
|
* case READ_CONTENT:
|
||||||
* ChannelBuffer frame = buf.readBytes(length);
|
* ByteBuf frame = buf.readBytes(length);
|
||||||
* <strong>checkpoint(MyDecoderState.READ_LENGTH);</strong>
|
* <strong>checkpoint(MyDecoderState.READ_LENGTH);</strong>
|
||||||
* return frame;
|
* return frame;
|
||||||
* default:
|
* default:
|
||||||
@ -205,16 +199,14 @@ import io.netty.util.internal.Signal;
|
|||||||
* An alternative way to manage the decoder state is to manage it by yourself.
|
* An alternative way to manage the decoder state is to manage it by yourself.
|
||||||
* <pre>
|
* <pre>
|
||||||
* public class IntegerHeaderFrameDecoder
|
* public class IntegerHeaderFrameDecoder
|
||||||
* extends {@link ReplayingDecoder}<<strong>{@link Void}</strong>> {
|
* extends {@link ReplayingDecoder}<{@link ByteBuf},<strong>{@link Void}</strong>> {
|
||||||
*
|
*
|
||||||
* <strong>private boolean readLength;</strong>
|
* <strong>private boolean readLength;</strong>
|
||||||
* private int length;
|
* private int length;
|
||||||
*
|
*
|
||||||
* {@code @Override}
|
* {@code @Override}
|
||||||
* protected Object decode({@link ChannelHandlerContext} ctx,
|
* protected {@link ByteBuf} decode({@link ChannelHandlerContext} ctx,
|
||||||
* {@link Channel} channel,
|
* {@link ByteBuf} in) throws Exception {
|
||||||
* {@link ByteBuf} buf,
|
|
||||||
* {@link Void} state) throws Exception {
|
|
||||||
* if (!readLength) {
|
* if (!readLength) {
|
||||||
* length = buf.readInt();
|
* length = buf.readInt();
|
||||||
* <strong>readLength = true;</strong>
|
* <strong>readLength = true;</strong>
|
||||||
@ -222,7 +214,7 @@ import io.netty.util.internal.Signal;
|
|||||||
* }
|
* }
|
||||||
*
|
*
|
||||||
* if (readLength) {
|
* if (readLength) {
|
||||||
* ChannelBuffer frame = buf.readBytes(length);
|
* ByteBuf frame = buf.readBytes(length);
|
||||||
* <strong>readLength = false;</strong>
|
* <strong>readLength = false;</strong>
|
||||||
* <strong>checkpoint();</strong>
|
* <strong>checkpoint();</strong>
|
||||||
* return frame;
|
* return frame;
|
||||||
@ -235,31 +227,26 @@ import io.netty.util.internal.Signal;
|
|||||||
* <p>
|
* <p>
|
||||||
* If you are going to write a protocol multiplexer, you will probably want to
|
* If you are going to write a protocol multiplexer, you will probably want to
|
||||||
* replace a {@link ReplayingDecoder} (protocol detector) with another
|
* replace a {@link ReplayingDecoder} (protocol detector) with another
|
||||||
* {@link ReplayingDecoder} or {@link FrameDecoder} (actual protocol decoder).
|
* {@link ReplayingDecoder}, {@link ByteToByteDecoder}, {@link ByteToMessageDecoder} or {@link MessageToMessageDecoder}
|
||||||
|
* (actual protocol decoder).
|
||||||
* It is not possible to achieve this simply by calling
|
* It is not possible to achieve this simply by calling
|
||||||
* {@link ChannelPipeline#replace(ChannelHandler, String, ChannelHandler)}, but
|
* {@link ChannelPipeline#replace(ChannelHandler, String, ChannelHandler)}, but
|
||||||
* some additional steps are required:
|
* some additional steps are required:
|
||||||
* <pre>
|
* <pre>
|
||||||
* public class FirstDecoder extends {@link ReplayingDecoder}<{@link Void}> {
|
* public class FirstDecoder extends {@link ReplayingDecoder}<{@link Object}, {@link Void}> {
|
||||||
*
|
|
||||||
* public FirstDecoder() {
|
|
||||||
* super(true); // Enable unfold
|
|
||||||
* }
|
|
||||||
*
|
*
|
||||||
* {@code @Override}
|
* {@code @Override}
|
||||||
* protected Object decode({@link ChannelHandlerContext} ctx,
|
* protected Object decode({@link ChannelHandlerContext} ctx,
|
||||||
* {@link Channel} ch,
|
* {@link ByteBuf} in) {
|
||||||
* {@link ByteBuf} buf,
|
|
||||||
* {@link Void} state) {
|
|
||||||
* ...
|
* ...
|
||||||
* // Decode the first message
|
* // Decode the first message
|
||||||
* Object firstMessage = ...;
|
* Object firstMessage = ...;
|
||||||
*
|
*
|
||||||
* // Add the second decoder
|
* // Add the second decoder
|
||||||
* ctx.getPipeline().addLast("second", new SecondDecoder());
|
* ctx.pipeline().addLast("second", new SecondDecoder());
|
||||||
*
|
*
|
||||||
* // Remove the first decoder (me)
|
* // Remove the first decoder (me)
|
||||||
* ctx.getPipeline().remove(this);
|
* ctx.pipeline().remove(this);
|
||||||
*
|
*
|
||||||
* if (buf.readable()) {
|
* if (buf.readable()) {
|
||||||
* // Hand off the remaining data to the second decoder
|
* // Hand off the remaining data to the second decoder
|
||||||
|
@ -31,6 +31,9 @@ import java.nio.channels.GatheringByteChannel;
|
|||||||
import java.nio.channels.ScatteringByteChannel;
|
import java.nio.channels.ScatteringByteChannel;
|
||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Special {@link ByteBuf} implementation which is used by the {@link ReplayingDecoder}
|
||||||
|
*/
|
||||||
final class ReplayingDecoderBuffer implements ByteBuf {
|
final class ReplayingDecoderBuffer implements ByteBuf {
|
||||||
|
|
||||||
private static final Signal REPLAY = ReplayingDecoder.REPLAY;
|
private static final Signal REPLAY = ReplayingDecoder.REPLAY;
|
||||||
|
@ -16,8 +16,8 @@
|
|||||||
package io.netty.handler.codec;
|
package io.netty.handler.codec;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An {@link Exception} which is thrown when the length of the frame
|
* An {@link DecoderException} which is thrown when the length of the frame
|
||||||
* decoded by {@link DelimiterBasedFrameDecoder} is greater than the maximum.
|
* decoded is greater than the allowed maximum.
|
||||||
*
|
*
|
||||||
* @apiviz.exclude
|
* @apiviz.exclude
|
||||||
*/
|
*/
|
||||||
|
@ -15,11 +15,9 @@
|
|||||||
*/
|
*/
|
||||||
package io.netty.handler.codec;
|
package io.netty.handler.codec;
|
||||||
|
|
||||||
import io.netty.buffer.ByteBuf;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An {@link Exception} which is thrown when a user calls an unsupported
|
* An {@link UnsupportedOperationException} which is thrown when a user calls an unsupported
|
||||||
* operation on a {@link ByteBuf} in a {@link ReplayingDecoder}
|
* operation on a {@link ReplayingDecoderBuffer} in a {@link ReplayingDecoder}
|
||||||
* implementation.
|
* implementation.
|
||||||
*/
|
*/
|
||||||
public class UnreplayableOperationException extends UnsupportedOperationException {
|
public class UnreplayableOperationException extends UnsupportedOperationException {
|
||||||
|
@ -15,6 +15,9 @@
|
|||||||
*/
|
*/
|
||||||
package io.netty.handler.codec;
|
package io.netty.handler.codec;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Thrown if an unsupported message is received by an codec.
|
||||||
|
*/
|
||||||
public class UnsupportedMessageTypeException extends CodecException {
|
public class UnsupportedMessageTypeException extends CodecException {
|
||||||
|
|
||||||
private static final long serialVersionUID = 2799598826487038726L;
|
private static final long serialVersionUID = 2799598826487038726L;
|
||||||
|
@ -28,9 +28,7 @@ import java.net.SocketAddress;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* A {@link ChannelHandler} that logs all events via {@link InternalLogger}.
|
* A {@link ChannelHandler} that logs all events via {@link InternalLogger}.
|
||||||
* By default, all events are logged at <tt>DEBUG</tt> level. You can extend
|
* By default, all events are logged at <tt>DEBUG</tt> level.
|
||||||
* this class and override {@link #log(ChannelEvent)} to change the default
|
|
||||||
* behavior.
|
|
||||||
* @apiviz.landmark
|
* @apiviz.landmark
|
||||||
*/
|
*/
|
||||||
@Sharable
|
@Sharable
|
||||||
@ -118,7 +116,6 @@ public class LoggingHandler extends ChannelHandlerAdapter {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the {@link InternalLogLevel} that this handler uses to log
|
* Returns the {@link InternalLogLevel} that this handler uses to log
|
||||||
* a {@link ChannelEvent}.
|
|
||||||
*/
|
*/
|
||||||
public LogLevel level() {
|
public LogLevel level() {
|
||||||
return level;
|
return level;
|
||||||
|
Loading…
Reference in New Issue
Block a user