org.jboss.netty.handler.codec.frame

## Class FrameDecoder

- java.lang.Object
- - org.jboss.netty.channel.SimpleChannelUpstreamHandler
  - - org.jboss.netty.handler.codec.frame.FrameDecoder

- All Implemented Interfaces:
    ChannelHandler, ChannelUpstreamHandler, LifeCycleAwareChannelHandler
  Direct Known Subclasses:
    DelimiterBasedFrameDecoder, FixedLengthFrameDecoder, LengthFieldBasedFrameDecoder, ProtobufVarint32FrameDecoder, ReplayingDecoder, SpdyFrameDecoder, SslHandler

      public abstract class FrameDecoder
      extends SimpleChannelUpstreamHandler
      implements LifeCycleAwareChannelHandler

  Decodes the received `ChannelBuffer`s into a meaningful frame object.

  In a stream-based transport such as TCP/IP, packets can be fragmented and reassembled during transmission even in a LAN environment. For example, let us assume you have received three packets:

       +-----+-----+-----+
       | ABC | DEF | GHI |
       +-----+-----+-----+

  because of the packet fragmentation, a server can receive them like the following:

       +----+-------+---+---+
       | AB | CDEFG | H | I |
       +----+-------+---+---+

  `FrameDecoder` helps you defrag the received packets into one or more meaningful frames that could be easily understood by the application logic. In case of the example above, your `FrameDecoder` implementation could defrag the received packets like the following:

       +-----+-----+-----+
       | ABC | DEF | GHI |
       +-----+-----+-----+

  The following code shows an example handler which decodes a frame whose first 4 bytes header represents the length of the frame, excluding the header.

       MESSAGE FORMAT
       ==============

       Offset:  0        4                   (Length + 4)
                +--------+------------------------+
       Fields:  | Length | Actual message content |
                +--------+------------------------+

       DECODER IMPLEMENTATION
       ======================

       public class IntegerHeaderFrameDecoder extends FrameDecoder {

         @Override
         protected Object decode(ChannelHandlerContext ctx,
                                 channel,
                                 ChannelBuffer buf) throws Exception {

           // Make sure if the length field was received.
           if (buf.readableBytes() < 4) {
              // The length field was not received yet - return null.
              // This method will be invoked again when more packets are
              // received and appended to the buffer.
              return null;
           }

           // The length field is in the buffer.

           // Mark the current buffer position before reading the length field
           // because the whole frame might not be in the buffer yet.
           // We will reset the buffer position to the marked position if
           // there's not enough bytes in the buffer.
           buf.markReaderIndex();

           // Read the length field.
           int length = buf.readInt();

           // Make sure if there's enough bytes in the buffer.
           if (buf.readableBytes() < length) {
              // The whole bytes were not received yet - return null.
              // This method will be invoked again when more packets are
              // received and appended to the buffer.

              // Reset to the marked position to read the length field again
              // next time.
              buf.resetReaderIndex();

              return null;
           }

           // There's enough bytes in the buffer. Read it.
           ChannelBuffer frame = buf.readBytes(length);

           // Successfully decoded a frame.  Return the decoded frame.
           return frame;
         }
       }

  ### Returning a POJO rather than a `ChannelBuffer`

  Please note that you can return an object of a different type than `ChannelBuffer` in your `decode()` and `decodeLast()` implementation. For example, you could return a POJO so that the next `ChannelUpstreamHandler` receives a `MessageEvent` which contains a POJO rather than a `ChannelBuffer`.

  ### Replacing a decoder with another decoder in a pipeline

  If you are going to write a protocol multiplexer, you will probably want to replace a `FrameDecoder` (protocol detector) with another `FrameDecoder` or `ReplayingDecoder` (actual protocol decoder). It is not possible to achieve this simply by calling `ChannelPipeline.replace(ChannelHandler, String, ChannelHandler)`, but some additional steps are required:

       public class FirstDecoder extends FrameDecoder {

           public FirstDecoder() {
               super(true); // Enable unfold
           }

           @Override
           protected Object decode(ChannelHandlerContext ctx,
                                   Channel channel,
                                   ChannelBuffer buf) {
               ...
               // Decode the first message
               Object firstMessage = ...;

               // Add the second decoder
               ctx.getPipeline().addLast("second", new SecondDecoder());

               // Remove the first decoder (me)
               ctx.getPipeline().remove(this);

               if (buf.readable()) {
                   // Hand off the remaining data to the second decoder
                   return new Object[] { firstMessage, buf.readBytes(buf.readableBytes()) };
               } else {
                   // Nothing to hand off
                   return firstMessage;
               }
           }
       }

- - ### Nested Class Summary

    - ### Nested classes/interfaces inherited from interface org.jboss.netty.channel.ChannelHandler

      `ChannelHandler.Sharable`

  - ### Field Summary

    Fields
    Modifier and Type | Field and Description
    --- | ---
    `protected ChannelBuffer` | `cumulation`
    `static int` | `DEFAULT_MAX_COMPOSITEBUFFER_COMPONENTS`

  - ### Constructor Summary

    Constructors
    Modifier | Constructor and Description
    --- | ---
    `protected` | `FrameDecoder()`
    `protected` | `FrameDecoder(boolean unfold)`

  - ### Method Summary

    Methods
    Modifier and Type | Method and Description
    --- | ---
    `protected int` | `actualReadableBytes()` Returns the actual number of readable bytes in the internal cumulative buffer of this decoder.
    `void` | `afterAdd(ChannelHandlerContext ctx)`
    `void` | `afterRemove(ChannelHandlerContext ctx)`
    `protected ChannelBuffer` | `appendToCumulation(ChannelBuffer input)`
    `void` | `beforeAdd(ChannelHandlerContext ctx)`
    `void` | `beforeRemove(ChannelHandlerContext ctx)`
    `void` | `channelClosed(ChannelHandlerContext ctx, ChannelStateEvent e)` Invoked when a `Channel` was closed and all its related resources were released.
    `void` | `channelDisconnected(ChannelHandlerContext ctx, ChannelStateEvent e)` Invoked when a `Channel` was disconnected from its remote peer.
    `protected void` | `cleanup(ChannelHandlerContext ctx, ChannelStateEvent e)` Gets called on `channelDisconnected(ChannelHandlerContext, ChannelStateEvent)` and `channelClosed(ChannelHandlerContext, ChannelStateEvent)`
    `protected abstract Object` | `decode(ChannelHandlerContext ctx, Channel channel, ChannelBuffer buffer)` Decodes the received packets so far into a frame.
    `protected Object` | `decodeLast(ChannelHandlerContext ctx, Channel channel, ChannelBuffer buffer)` Decodes the received data so far into a frame when the channel is disconnected.
    `void` | `exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e)` Invoked when an exception was raised by an I/O thread or a `ChannelHandler`.
    `int` | `getMaxCumulationBufferCapacity()` See `setMaxCumulationBufferCapacity(int)` for explaintation of this setting
    `int` | `getMaxCumulationBufferComponents()` Returns the maximum number of components in the cumulation buffer.
    `protected ChannelBuffer` | `internalBuffer()` Returns the internal cumulative buffer of this decoder.
    `boolean` | `isUnfold()`
    `void` | `messageReceived(ChannelHandlerContext ctx, MessageEvent e)` Invoked when a message object (e.g: `ChannelBuffer`) was received from a remote peer.
    `protected ChannelBuffer` | `newCumulationBuffer(ChannelHandlerContext ctx, int minimumCapacity)` Create a new `ChannelBuffer` which is used for the cumulation.
    `void` | `replace(String handlerName, ChannelHandler handler)` Replace this `FrameDecoder` in the `ChannelPipeline` with the given `ChannelHandler`.
    `void` | `setMaxCumulationBufferCapacity(int copyThreshold)` Set the maximal capacity of the internal cumulation ChannelBuffer to use before the `FrameDecoder` tries to minimize the memory usage by "byte copy".
    `void` | `setMaxCumulationBufferComponents(int maxCumulationBufferComponents)` Sets the maximum number of components in the cumulation buffer.
    `void` | `setUnfold(boolean unfold)`
    `protected void` | `unfoldAndFireMessageReceived(ChannelHandlerContext context, SocketAddress remoteAddress, Object result)`
    `protected ChannelBuffer` | `updateCumulation(ChannelHandlerContext ctx, ChannelBuffer input)`

    - ### Methods inherited from class org.jboss.netty.channel.SimpleChannelUpstreamHandler

      `channelBound, channelConnected, channelInterestChanged, channelOpen, channelUnbound, childChannelClosed, childChannelOpen, handleUpstream, writeComplete`

    - ### Methods inherited from class java.lang.Object

      `clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait`

- - ### Field Detail

    - #### DEFAULT_MAX_COMPOSITEBUFFER_COMPONENTS

          public static final int DEFAULT_MAX_COMPOSITEBUFFER_COMPONENTS

      See Also:
        Constant Field Values

    - #### cumulation

          protected ChannelBuffer cumulation

  - ### Constructor Detail

    - #### FrameDecoder

          protected FrameDecoder()

    - #### FrameDecoder

          protected FrameDecoder(boolean unfold)

  - ### Method Detail

    - #### isUnfold

          public final boolean isUnfold()

    - #### setUnfold

          public final void setUnfold(boolean unfold)

    - #### getMaxCumulationBufferCapacity

          public final int getMaxCumulationBufferCapacity()

      See `setMaxCumulationBufferCapacity(int)` for explaintation of this setting

    - #### setMaxCumulationBufferCapacity

          public final void setMaxCumulationBufferCapacity(int copyThreshold)

      Set the maximal capacity of the internal cumulation ChannelBuffer to use before the `FrameDecoder` tries to minimize the memory usage by "byte copy". What you use here really depends on your application and need. Using `Integer.MAX_VALUE` will disable all byte copies but give you the cost of a higher memory usage if big `ChannelBuffer`'s will be received. By default a threshold of `0` is used, which means it will always copy to try to reduce memory usage
      Parameters:
        `copyThreshold` - the threshold (in bytes) or `Integer.MAX_VALUE` to disable it. The value must be at least 0
      Throws:
        `IllegalStateException` - get thrown if someone tries to change this setting after the Decoder was added to the `ChannelPipeline`

    - #### getMaxCumulationBufferComponents

          public final int getMaxCumulationBufferComponents()

      Returns the maximum number of components in the cumulation buffer. If the number of the components in the cumulation buffer exceeds this value, the components of the cumulation buffer are consolidated into a single component, involving memory copies. The default value of this property `DEFAULT_MAX_COMPOSITEBUFFER_COMPONENTS`.

    - #### setMaxCumulationBufferComponents

          public final void setMaxCumulationBufferComponents(int maxCumulationBufferComponents)

      Sets the maximum number of components in the cumulation buffer. If the number of the components in the cumulation buffer exceeds this value, the components of the cumulation buffer are consolidated into a single component, involving memory copies. The default value of this property is `DEFAULT_MAX_COMPOSITEBUFFER_COMPONENTS` and its minimum allowed value is `2`.

    - #### messageReceived

          public void messageReceived(ChannelHandlerContext ctx,
                             MessageEvent e)
                               throws Exception

      Description copied from class: `SimpleChannelUpstreamHandler`
      Invoked when a message object (e.g: `ChannelBuffer`) was received from a remote peer.
      Overrides:
        `messageReceived` in class `SimpleChannelUpstreamHandler`
      Throws:
        `Exception`

    - #### appendToCumulation

          protected ChannelBuffer appendToCumulation(ChannelBuffer input)

    - #### updateCumulation

          protected ChannelBuffer updateCumulation(ChannelHandlerContext ctx,
                                       ChannelBuffer input)

    - #### channelDisconnected

          public void channelDisconnected(ChannelHandlerContext ctx,
                                 ChannelStateEvent e)
                                   throws Exception

      Description copied from class: `SimpleChannelUpstreamHandler`
      Invoked when a `Channel` was disconnected from its remote peer.
      Overrides:
        `channelDisconnected` in class `SimpleChannelUpstreamHandler`
      Throws:
        `Exception`

    - #### channelClosed

          public void channelClosed(ChannelHandlerContext ctx,
                           ChannelStateEvent e)
                             throws Exception

      Description copied from class: `SimpleChannelUpstreamHandler`
      Invoked when a `Channel` was closed and all its related resources were released.
      Overrides:
        `channelClosed` in class `SimpleChannelUpstreamHandler`
      Throws:
        `Exception`

    - #### exceptionCaught

          public void exceptionCaught(ChannelHandlerContext ctx,
                             ExceptionEvent e)
                               throws Exception

      Description copied from class: `SimpleChannelUpstreamHandler`
      Invoked when an exception was raised by an I/O thread or a `ChannelHandler`.
      Overrides:
        `exceptionCaught` in class `SimpleChannelUpstreamHandler`
      Throws:
        `Exception`

    - #### decode

          protected abstract Object decode(ChannelHandlerContext ctx,
                      Channel channel,
                      ChannelBuffer buffer)
                                    throws Exception

      Decodes the received packets so far into a frame.
      Parameters:
        `ctx` - the context of this handler
        `channel` - the current channel
        `buffer` - the cumulative buffer of received packets so far. Note that the buffer might be empty, which means you should not make an assumption that the buffer contains at least one byte in your decoder implementation.
      Returns:
        the decoded frame if a full frame was received and decoded. `null` if there's not enough data in the buffer to decode a frame.
      Throws:
        `Exception`

    - #### decodeLast

          protected Object decodeLast(ChannelHandlerContext ctx,
                          Channel channel,
                          ChannelBuffer buffer)
                               throws Exception

      Decodes the received data so far into a frame when the channel is disconnected.
      Parameters:
        `ctx` - the context of this handler
        `channel` - the current channel
        `buffer` - the cumulative buffer of received packets so far. Note that the buffer might be empty, which means you should not make an assumption that the buffer contains at least one byte in your decoder implementation.
      Returns:
        the decoded frame if a full frame was received and decoded. `null` if there's not enough data in the buffer to decode a frame.
      Throws:
        `Exception`

    - #### unfoldAndFireMessageReceived

          protected final void unfoldAndFireMessageReceived(ChannelHandlerContext context,
                                          SocketAddress remoteAddress,
                                          Object result)

    - #### cleanup

          protected void cleanup(ChannelHandlerContext ctx,
                     ChannelStateEvent e)
                          throws Exception

      Gets called on `channelDisconnected(ChannelHandlerContext, ChannelStateEvent)` and `channelClosed(ChannelHandlerContext, ChannelStateEvent)`
      Throws:
        `Exception`

    - #### newCumulationBuffer

          protected ChannelBuffer newCumulationBuffer(ChannelHandlerContext ctx,
                                          int minimumCapacity)

      Create a new `ChannelBuffer` which is used for the cumulation. Sub-classes may override this.
      Parameters:
        `ctx` - `ChannelHandlerContext` for this handler
      Returns:
        buffer the `ChannelBuffer` which is used for cumulation

    - #### replace

          public void replace(String handlerName,
                     ChannelHandler handler)

      Replace this `FrameDecoder` in the `ChannelPipeline` with the given `ChannelHandler`. All remaining bytes in the `ChannelBuffer` will get send to the new `ChannelHandler` that was used as replacement

    - #### actualReadableBytes

          protected int actualReadableBytes()

      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 muse use it at your own risk. This method is a shortcut to `internalBuffer().readableBytes()`.

    - #### internalBuffer

          protected ChannelBuffer internalBuffer()

      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.

    - #### beforeAdd

          public void beforeAdd(ChannelHandlerContext ctx)
                         throws Exception

      Specified by:
        `beforeAdd` in interface `LifeCycleAwareChannelHandler`
      Throws:
        `Exception`

    - #### afterAdd

          public void afterAdd(ChannelHandlerContext ctx)
                        throws Exception

      Specified by:
        `afterAdd` in interface `LifeCycleAwareChannelHandler`
      Throws:
        `Exception`

    - #### beforeRemove

          public void beforeRemove(ChannelHandlerContext ctx)
                            throws Exception

      Specified by:
        `beforeRemove` in interface `LifeCycleAwareChannelHandler`
      Throws:
        `Exception`

    - #### afterRemove

          public void afterRemove(ChannelHandlerContext ctx)
                           throws Exception

      Specified by:
        `afterRemove` in interface `LifeCycleAwareChannelHandler`
      Throws:
        `Exception`

Copyright © 2008-2012 The Netty Project. All Rights Reserved.