001: package org.apache.mina.filter.codec.prefixedstring;
002:
003: import org.apache.mina.common.IoBuffer;
004: import org.apache.mina.common.IoSession;
005: import org.apache.mina.common.BufferDataException;
006: import org.apache.mina.filter.codec.CumulativeProtocolDecoder;
007: import org.apache.mina.filter.codec.ProtocolDecoder;
008: import org.apache.mina.filter.codec.ProtocolDecoderOutput;
009:
010: import java.nio.charset.Charset;
011:
012: /**
013: * A {@link ProtocolDecoder} which decodes a String using a fixed-length length prefix.
014: *
015: * @author The Apache MINA Project (dev@mina.apache.org)
016: * @version $Rev: 591182 $, $Date: 2007-11-02 01:59:27 +0100 (vr, 02 nov 2007) $,
017: */
018: public class PrefixedStringDecoder extends CumulativeProtocolDecoder {
019:
020: public final static int DEFAULT_PREFIX_LENGTH = 4;
021:
022: public final static int DEFAULT_MAX_DATA_LENGTH = 2048;
023:
024: private final Charset charset;
025:
026: private int prefixLength = DEFAULT_PREFIX_LENGTH;
027:
028: private int maxDataLength = DEFAULT_MAX_DATA_LENGTH;
029:
030: /**
031: * @param charset the charset to use for encoding
032: * @param prefixLength the length of the prefix
033: * @param maxDataLength maximum number of bytes allowed for a single String
034: */
035: public PrefixedStringDecoder(Charset charset, int prefixLength,
036: int maxDataLength) {
037: this .charset = charset;
038: this .prefixLength = prefixLength;
039: this .maxDataLength = maxDataLength;
040: }
041:
042: public PrefixedStringDecoder(Charset charset, int prefixLength) {
043: this (charset, prefixLength, DEFAULT_MAX_DATA_LENGTH);
044: }
045:
046: public PrefixedStringDecoder(Charset charset) {
047: this (charset, DEFAULT_PREFIX_LENGTH);
048: }
049:
050: /**
051: * Sets the number of bytes used by the length prefix
052: *
053: * @param prefixLength the length of the length prefix (1, 2, or 4)
054: */
055: public void setPrefixLength(int prefixLength) {
056: this .prefixLength = prefixLength;
057: }
058:
059: /**
060: * Gets the length of the length prefix (1, 2, or 4)
061: *
062: * @return length of the length prefix
063: */
064: public int getPrefixLength() {
065: return prefixLength;
066: }
067:
068: /**
069: * Sets the maximum allowed value specified as data length in the incoming data
070: * <p>
071: * Useful for preventing an OutOfMemory attack by the peer.
072: * The decoder will throw a {@link BufferDataException} when data length
073: * specified in the incoming data is greater than maxDataLength
074: * The default value is {@link PrefixedStringDecoder#DEFAULT_MAX_DATA_LENGTH}.
075: * </p>
076: *
077: * @param maxDataLength maximum allowed value specified as data length in the incoming data
078: */
079: public void setMaxDataLength(int maxDataLength) {
080: this .maxDataLength = maxDataLength;
081: }
082:
083: /**
084: * Gets the maximum number of bytes allowed for a single String
085: *
086: * @return maximum number of bytes allowed for a single String
087: */
088: public int getMaxDataLength() {
089: return maxDataLength;
090: }
091:
092: protected boolean doDecode(IoSession session, IoBuffer in,
093: ProtocolDecoderOutput out) throws Exception {
094: if (in.prefixedDataAvailable(prefixLength, maxDataLength)) {
095: String msg = in.getPrefixedString(prefixLength, charset
096: .newDecoder());
097: out.write(msg);
098: return true;
099: } else {
100: return false;
101: }
102: }
103: }
|