All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.netty.handler.codec.ByteToByteDecoder Maven / Gradle / Ivy

There is a newer version: 5.0.0.Alpha2
Show newest version
/*
 * 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 (Throwable t) { if (t instanceof CodecException) { ctx.fireExceptionCaught(t); } else { ctx.fireExceptionCaught(new DecoderException(t)); } } 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(); while (in.isReadable()) { int oldInSize = in.readableBytes(); try { decode(ctx, in, out); } catch (Throwable t) { if (t instanceof CodecException) { ctx.fireExceptionCaught(t); } else { ctx.fireExceptionCaught(new DecoderException(t)); } } if (oldInSize == in.readableBytes() || isSingleDecode()) { break; } } 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); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy