View Javadoc

    1   /*
    2    *  Licensed to the Apache Software Foundation (ASF) under one
    3    *  or more contributor license agreements.  See the NOTICE file
    4    *  distributed with this work for additional information
    5    *  regarding copyright ownership.  The ASF licenses this file
    6    *  to you under the Apache License, Version 2.0 (the
    7    *  "License"); you may not use this file except in compliance
    8    *  with the License.  You may obtain a copy of the License at
    9    *
    10   *    http://www.apache.org/licenses/LICENSE-2.0
    11   *
    12   *  Unless required by applicable law or agreed to in writing,
    13   *  software distributed under the License is distributed on an
    14   *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    15   *  KIND, either express or implied.  See the License for the
    16   *  specific language governing permissions and limitations
    17   *  under the License.
    18   *
    19   */
    20  package org.apache.mina.filter.codec.prefixedstring;
    21
    22  import org.apache.mina.core.buffer.BufferDataException;
    23  import org.apache.mina.core.buffer.IoBuffer;
    24  import org.apache.mina.core.session.IoSession;
    25  import org.apache.mina.filter.codec.CumulativeProtocolDecoder;
    26  import org.apache.mina.filter.codec.ProtocolDecoder;
    27  import org.apache.mina.filter.codec.ProtocolDecoderOutput;
    28
    29  import java.nio.charset.Charset;
    30
    31  /**
    32   * A {@link ProtocolDecoder} which decodes a String using a fixed-length length prefix.
    33   *
    34   * @author <a href="http://mina.apache.org">Apache MINA Project</a>
    35   */
    36  public class PrefixedStringDecoder extends CumulativeProtocolDecoder {
    37
    38      public final static int DEFAULT_PREFIX_LENGTH = 4;
    39
    40      public final static int DEFAULT_MAX_DATA_LENGTH = 2048;
    41
    42      private final Charset charset;
    43
    44      private int prefixLength = DEFAULT_PREFIX_LENGTH;
    45
    46      private int maxDataLength = DEFAULT_MAX_DATA_LENGTH;
    47
    48      /**
    49       * @param charset       the charset to use for encoding
    50       * @param prefixLength  the length of the prefix
    51       * @param maxDataLength maximum number of bytes allowed for a single String
    52       */
    53      public PrefixedStringDecoder(Charset charset, int prefixLength, int maxDataLength) {
    54          this.charset = charset;
    55          this.prefixLength = prefixLength;
    56          this.maxDataLength = maxDataLength;
    57      }
    58
    59      public PrefixedStringDecoder(Charset charset, int prefixLength) {
    60          this(charset, prefixLength, DEFAULT_MAX_DATA_LENGTH);
    61      }
    62
    63      public PrefixedStringDecoder(Charset charset) {
    64          this(charset, DEFAULT_PREFIX_LENGTH);
    65      }
    66
    67      /**
    68       * Sets the number of bytes used by the length prefix
    69       *
    70       * @param prefixLength the length of the length prefix (1, 2, or 4)
    71       */
    72      public void setPrefixLength(int prefixLength) {
    73          this.prefixLength = prefixLength;
    74      }
    75
    76      /**
    77       * Gets the length of the length prefix (1, 2, or 4)
    78       *
    79       * @return length of the length prefix
    80       */
    81      public int getPrefixLength() {
    82          return prefixLength;
    83      }
    84
    85      /**
    86       * Sets the maximum allowed value specified as data length in the incoming data
    87       * <p>
    88       * Useful for preventing an OutOfMemory attack by the peer.
    89       * The decoder will throw a {@link BufferDataException} when data length
    90       * specified in the incoming data is greater than maxDataLength
    91       * The default value is {@link PrefixedStringDecoder#DEFAULT_MAX_DATA_LENGTH}.
    92       * </p>
    93       *
    94       * @param maxDataLength maximum allowed value specified as data length in the incoming data
    95       */
    96      public void setMaxDataLength(int maxDataLength) {
    97          this.maxDataLength = maxDataLength;
    98      }
    99
    100     /**
    101      * Gets the maximum number of bytes allowed for a single String
    102      *
    103      * @return maximum number of bytes allowed for a single String
    104      */
    105     public int getMaxDataLength() {
    106         return maxDataLength;
    107     }
    108
    109     protected boolean doDecode(IoSession session, IoBuffer in, ProtocolDecoderOutput out) throws Exception {
    110         if (in.prefixedDataAvailable(prefixLength, maxDataLength)) {
    111             String msg = in.getPrefixedString(prefixLength, charset.newDecoder());
    112             out.write(msg);
    113             return true;
    114         }
    115
    116         return false;
    117     }
    118 }