Package de.fhkn.in.uce.stun.attribute

Source Code of de.fhkn.in.uce.stun.attribute.AttributeHeaderDecoder$AttributeHeaderImpl

/*
* Copyright (c) 2012 Alexander Diener,
*
* This program is free software: you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
package de.fhkn.in.uce.stun.attribute;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;

import de.fhkn.in.uce.stun.util.MessageFormatException;

/**
* Class to decode byte encoded attribute headers.
*
* @author Daniel Maier, Alexander Diener (aldiener@htwg-konstanz.de)
*
*/
public final class AttributeHeaderDecoder {
    private final AttributeTypeDecoder commonAttributeTypeDecoder;
    private final List<AttributeTypeDecoder> customAttributeTypeDecoders;

    /**
     * Creates a new {@link AttributeHeaderDecoder}.
     */
    AttributeHeaderDecoder() {
        this(new ArrayList<AttributeTypeDecoder>());
    }

    /**
     * Creates a new {@link AttributeHeaderDecoder} with the specified
     * {@link AttributeTypeDecoder} to decode custom attribute types.
     *
     * @param customAttributeTypeDecoder
     *            a list of {@link AttributeTypeDecoder} to decode custom
     *            attribute types
     * @throws NullPointerException
     *             if the specified {@link AttributeTypeDecoder} is null
     */
    AttributeHeaderDecoder(final List<AttributeTypeDecoder> customAttributeTypeDecoders) {
        if (customAttributeTypeDecoders == null) {
            throw new NullPointerException();
        }
        this.commonAttributeTypeDecoder = new STUNAttributeTypeDecoder();
        this.customAttributeTypeDecoders = customAttributeTypeDecoders;
    }

    /**
     * Decodes the specified byte array to a {@link AttributeHeader} instance.
     *
     * @param encoded
     *            the byte encoded attribute header
     * @return the decoded attribute header
     * @throws IOException
     *             if an I/O error occurs if the encoded attribute header is
     *             malformed
     * @throws MessageFormatException
     * @throws NullPointerException
     *             if the specified byte array is null
     */
    public AttributeHeader decodeSTUNAttributeHeader(final byte[] encoded) throws IOException, MessageFormatException {
        this.checkHeaderLength(encoded);
        final ByteArrayInputStream bin = new ByteArrayInputStream(encoded);
        final DataInputStream din = new DataInputStream(bin);
        final int typeBits = din.readUnsignedShort();
        final AttributeType type = this.decodeAttributeType(typeBits);
        final int length = din.readUnsignedShort();
        return new AttributeHeaderImpl(type, length);
    }

    private void checkHeaderLength(final byte[] encodedHeader) throws MessageFormatException {
        if (encodedHeader == null) {
            throw new NullPointerException();
        } else if (encodedHeader.length != AttributeHeader.HEADER_LENGTH) {
            throw new MessageFormatException("Header has not the expected length"); //$NON-NLS-1$
        }
    }

    private AttributeType decodeAttributeType(final int attributeTypeBits) throws MessageFormatException {
        AttributeType result = this.decodeAttributeTypeWithCommonDecoder(attributeTypeBits);
        if (result == null) {
            result = this.decodeAttributeTypeWithCustomDecoders(attributeTypeBits);
            if (result == null) {
                // TODO this could be a comprehension-optional attribute, check
                // it and do something useful, if comprehension-required throw
                // exception
                result = STUNAttributeType.UNKNOWN_ATTRIBUTES;
            }
        }
        return result;
    }

    private AttributeType decodeAttributeTypeWithCommonDecoder(final int attributeTypeBits) {
        AttributeType result = null;
        result = this.commonAttributeTypeDecoder.decode(attributeTypeBits);
        return result;
    }

    private AttributeType decodeAttributeTypeWithCustomDecoders(final int attributeTypeBits) {
        AttributeType result = null;
        for (final AttributeTypeDecoder customDecoder : this.customAttributeTypeDecoders) {
            result = customDecoder.decode(attributeTypeBits);
            if (result != null) {
                break;
            }
        }
        return result;
    }

    @SuppressWarnings("unused")
    private boolean isComprehensionOptional(final int typeBits) {
        boolean result = false;
        if ((typeBits >= 0x8000) && (typeBits <= 0xFFFF)) {
            result = true;
        }
        return result;
    }

    /**
     * Implementation of a {@link AttributeHeader}.
     *
     * @author Daniel Maier, Alexander Diener (aldiener@htwg-konstanz.de)
     *
     */
    static final class AttributeHeaderImpl implements AttributeHeader {

        private final AttributeType type;
        private final int length;

        /**
         * Creates a new {@link AttributeHeaderImpl} with the specified
         * {@link AttributeType} and length.
         *
         * @param type
         *            the attribute type of this header
         * @param length
         *            the length of the attribute
         */
        AttributeHeaderImpl(final AttributeType type, final int length) {
            this.type = type;
            this.length = length;
        }

        @Override
        public AttributeType getType() {
            return this.type;
        }

        @Override
        public int getLength() {
            return this.length;
        }

        @Override
        public void writeTo(final OutputStream out) throws IOException {
            final ByteArrayOutputStream bout = new ByteArrayOutputStream();
            final DataOutputStream dout = new DataOutputStream(bout);
            dout.writeInt(this.type.encode());
            dout.writeInt(this.length);
            out.write(bout.toByteArray());
            out.flush();
        }

        @Override
        public int hashCode() {
            final int prime = 31;
            int result = 1;
            result = (prime * result) + this.length;
            result = (prime * result) + ((this.type == null) ? 0 : this.type.hashCode());
            return result;
        }

        @Override
        public boolean equals(final Object obj) {
            if (this == obj) {
                return true;
            }
            if (obj == null) {
                return false;
            }
            if (this.getClass() != obj.getClass()) {
                return false;
            }
            final AttributeHeaderImpl other = (AttributeHeaderImpl) obj;
            if (this.length != other.length) {
                return false;
            }
            if (this.type == null) {
                if (other.type != null) {
                    return false;
                }
            } else if (!this.type.equals(other.type)) {
                return false;
            }
            return true;
        }
    }
}
TOP

Related Classes of de.fhkn.in.uce.stun.attribute.AttributeHeaderDecoder$AttributeHeaderImpl

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.