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

io.netty.handler.codec.LineBasedFrameDecoder 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;

/**
 * A decoder that splits the received {@link ByteBuf}s on line endings.
 * 

* Both {@code "\n"} and {@code "\r\n"} are handled. * For a more general delimiter-based decoder, see {@link DelimiterBasedFrameDecoder}. */ public class LineBasedFrameDecoder extends ByteToMessageDecoder { /** Maximum length of a frame we're willing to decode. */ private final int maxLength; /** Whether or not to throw an exception as soon as we exceed maxLength. */ private final boolean failFast; private final boolean stripDelimiter; /** True if we're discarding input because we're already over maxLength. */ private boolean discarding; /** * Creates a new decoder. * @param maxLength the maximum length of the decoded frame. * A {@link TooLongFrameException} is thrown if * the length of the frame exceeds this value. */ public LineBasedFrameDecoder(final int maxLength) { this(maxLength, true, false); } /** * Creates a new decoder. * @param maxLength the maximum length of the decoded frame. * A {@link TooLongFrameException} is thrown if * the length of the frame exceeds this value. * @param stripDelimiter whether the decoded frame should strip out the * delimiter or not * @param failFast If true, a {@link TooLongFrameException} is * thrown as soon as the decoder notices the length of the * frame will exceed maxFrameLength regardless of * whether the entire frame has been read. * If false, a {@link TooLongFrameException} is * thrown after the entire frame that exceeds * maxFrameLength has been read. */ public LineBasedFrameDecoder(final int maxLength, final boolean stripDelimiter, final boolean failFast) { this.maxLength = maxLength; this.failFast = failFast; this.stripDelimiter = stripDelimiter; } @Override protected Object decode(ChannelHandlerContext ctx, ByteBuf buffer) throws Exception { final int eol = findEndOfLine(buffer); if (eol != -1) { final ByteBuf frame; final int length = eol - buffer.readerIndex(); assert length >= 0: "Invalid length=" + length; if (discarding) { frame = null; buffer.skipBytes(length); if (!failFast) { fail(ctx, "over " + (maxLength + length) + " bytes"); } } else { int delimLength; final byte delim = buffer.getByte(buffer.readerIndex() + length); if (delim == '\r') { delimLength = 2; // Skip the \r\n. } else { delimLength = 1; } if (stripDelimiter) { frame = buffer.readBytes(length); buffer.skipBytes(delimLength); } else { frame = buffer.readBytes(length + delimLength); } } return frame; } final int buffered = buffer.readableBytes(); if (!discarding && buffered > maxLength) { discarding = true; if (failFast) { fail(ctx, buffered + " bytes buffered already"); } } if (discarding) { buffer.skipBytes(buffer.readableBytes()); } return null; } private void fail(final ChannelHandlerContext ctx, final String msg) { ctx.fireExceptionCaught(new TooLongFrameException("Frame length exceeds " + maxLength + " (" + msg + ')')); } /** * Returns the index in the buffer of the end of line found. * Returns -1 if no end of line was found in the buffer. */ private static int findEndOfLine(final ByteBuf buffer) { final int n = buffer.writerIndex(); for (int i = buffer.readerIndex(); i < n; i ++) { final byte b = buffer.getByte(i); if (b == '\n') { return i; } else if (b == '\r' && i < n - 1 && buffer.getByte(i + 1) == '\n') { return i; // \r\n } } return -1; // Not found. } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy