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

org.littleshoot.stun.stack.StunDemuxableProtocolCodecFactory Maven / Gradle / Ivy

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

import org.littleshoot.mina.common.ByteBuffer;
import org.littleshoot.mina.filter.codec.ProtocolEncoder;
import org.littleshoot.stun.stack.decoder.StunMessageDecodingState;
import org.littleshoot.stun.stack.encoder.StunProtocolEncoder;
import org.littleshoot.stun.stack.message.StunMessage;
import org.littleshoot.util.mina.DecodingStateMachine;
import org.littleshoot.util.mina.DemuxableProtocolCodecFactory;
import org.littleshoot.util.mina.DemuxableProtocolDecoder;
import org.littleshoot.util.mina.DemuxingStateMachineProtocolDecoder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * {@link DemuxableProtocolCodecFactory} for STUN.
 */
public class StunDemuxableProtocolCodecFactory 
    implements DemuxableProtocolCodecFactory
    {

    private final Logger m_log = LoggerFactory.getLogger(getClass());
    
    public boolean canDecode(final ByteBuffer in)
        {
        if (!enoughData(in))
            {
            throw new IllegalArgumentException(
                "Not enough data to determine if we can decode it or not!!");
            }
        final int pos = in.position();
        final int limit = in.limit();
        try
            {
            final int firstByte = in.getUnsigned();
            
            // The first 2 bits of STUN messages are always zero.
            final int masked = firstByte & 0xc0;
            if (masked > 0)
                {
                return false;
                }
            else 
                {
                // OK, it could be a STUN message.  Let's check the 
                // STUN magic cookie field to make sure.
                final long magicCookie = 0x2112A442;
                final long secondFourBytes = in.getUnsignedInt(pos + 4);

                final boolean magicCookieMatches = 
                    secondFourBytes == magicCookie;
                
                m_log.debug("Magic cookie matches: "+
                    magicCookieMatches);
                return magicCookieMatches;
                }
            }
        finally
            {
            // Make sure we reset the buffer!
            in.position(pos);
            in.limit(limit);
            }
        }

    public Class getClassToEncode()
        {
        return StunMessage.class;
        }

    public DemuxableProtocolDecoder newDecoder()
        {
        final DecodingStateMachine startState = 
            new StunMessageDecodingState();
        return new DemuxingStateMachineProtocolDecoder(startState);
        }

    public ProtocolEncoder newEncoder()
        {
        return new StunProtocolEncoder();
        }

    public boolean enoughData(final ByteBuffer in)
        {
        //0                   1                   2                   3
        //0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
        //+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        //|0 0|     STUN Message Type     |         Message Length        |
        //+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        //|                         Magic Cookie                          |
        //+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        //|                                                               |
        //|                     Transaction ID (96 bits)                  |
        //|                                                               |
        //+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        
        // As you can see from the above diagram, we need 8 bytes total to
        // read the magic cookie.  Anything less than this, and we can't 
        // reliably determine whether or not it's a STUN message.
        return in.remaining() >= 8;
        }

    }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy