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

org.littleshoot.stun.stack.message.AbstractStunMessage Maven / Gradle / Ivy

The newest version!
package org.littleshoot.stun.stack.message;

import java.net.InetSocketAddress;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.id.uuid.UUID;
import org.littleshoot.mina.common.ByteBuffer;
import org.littleshoot.stun.stack.message.attributes.StunAttribute;
import org.littleshoot.stun.stack.message.attributes.StunAttributeType;
import org.littleshoot.stun.stack.message.attributes.turn.RemoteAddressAttribute;
import org.littleshoot.util.mina.MinaUtils;

/**
 * Abstracts out common methods and data of STUN messages.
 */
public abstract class AbstractStunMessage implements StunMessage
    {

    private static final Map EMPTY_MAP =
        Collections.emptyMap();
    
    private final UUID m_transactionId;
    private final Map m_attributes;

    private final int m_totalLength;

    private final int m_bodyLength;

    private final StunMessageType m_messageType;
    
    private static final int MAGIC_COOKIE = 0x2112A442;
    
    private static final ByteBuffer MAGIC_COOKIE_BUF = ByteBuffer.allocate(4);
    
    static
        {
        MAGIC_COOKIE_BUF.putInt(0x2112A442);
        }
    
    /**
     * Creates a new STUN message.
     * 
     * @param messageType The type of message.
     */
    public AbstractStunMessage(final StunMessageType messageType)
        {
        this(createTransactionId(), messageType, EMPTY_MAP);
        }
    
    /**
     * Creates a new STUN message.
     * 
     * @param attributes The message attributes.
     * @param messageType The type of the message.
     */
    public AbstractStunMessage(final StunMessageType messageType,
        final Map attributes)
        {
        this (createTransactionId(), messageType, attributes);
        }

    /**
     * Creates a new STUN message.
     * 
     * @param transactionId The transaction ID.
     * @param messageType The type of message.
     */
    public AbstractStunMessage(final UUID transactionId,
        final StunMessageType messageType)
        {
        this (transactionId, messageType, EMPTY_MAP);
        }
    
    /**
     * Creates a new STUN message.
     * 
     * @param transactionId The transaction ID.
     * @param attributes The message attributes.
     * @param messageType The type of the message.
     */
    public AbstractStunMessage(final UUID transactionId, 
        final StunMessageType messageType,
        final Map attributes)
        {
        m_transactionId = transactionId;
        m_attributes = attributes;
        m_bodyLength = calculateBodyLength(attributes);
        m_totalLength = m_bodyLength + 20;
        m_messageType = messageType;
        }
    
    private static UUID createTransactionId()
        {
        final UUID id = UUID.randomUUID();
        final byte[] idBytes = id.getRawBytes();
        final ByteBuffer idBuf = ByteBuffer.wrap(idBytes);
        
        // Lower the limit to make room for the magic cookie.
        idBuf.limit(idBytes.length - 4);
        
        final ByteBuffer newIdBuf = ByteBuffer.allocate(16);
        MinaUtils.putUnsignedInt(newIdBuf, MAGIC_COOKIE);
        newIdBuf.put(idBuf);
        newIdBuf.flip();
        
        return new UUID(MinaUtils.toByteArray(newIdBuf));
        }


    protected static Map createAttributes(
        final StunAttribute... attributes)
        {
        final Map attributesMap = 
            new HashMap();
        
        for (final StunAttribute attribute : attributes)
            {
            attributesMap.put(attribute.getAttributeType(), 
                attribute);
            }
        return attributesMap;
        }
    
    protected static Map createRemoteAddress(
        final InetSocketAddress remoteAddress)
        {
        final RemoteAddressAttribute att = 
            new RemoteAddressAttribute(remoteAddress);
        return createAttributes(att);
        }

    private static int calculateBodyLength(
        final Map attributesMap)
        {
        final Collection attributes = attributesMap.values();
        int length = 0;
        for (final StunAttribute attribute : attributes)
            {
            length += attribute.getTotalLength();
            }
        return length;
        }

    public UUID getTransactionId()
        {
        return this.m_transactionId;
        }

    public int getTotalLength()
        {
        return this.m_totalLength;
        }

    public Map getAttributes()
        {
        return m_attributes;
        }
    
    public int getBodyLength()
        {
        return this.m_bodyLength;
        }
    
    public StunMessageType getType()
        {
        return this.m_messageType;
        }
    
    public String toString()
        {
        return getClass().getSimpleName() + " " + 
            this.m_attributes + " body length: "+this.m_bodyLength;
        }
    }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy