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

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

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

import java.net.PortUnreachableException;

import org.littleshoot.mina.common.IdleStatus;
import org.littleshoot.mina.common.IoHandlerAdapter;
import org.littleshoot.mina.common.IoSession;
import org.littleshoot.mina.util.SessionUtil;
import org.littleshoot.stun.stack.message.ConnectErrorStunMessage;
import org.littleshoot.stun.stack.message.StunMessage;
import org.littleshoot.stun.stack.message.StunMessageVisitor;
import org.littleshoot.stun.stack.message.StunMessageVisitorFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Processes STUN messages.  This class can be sub-classed to implement 
 * specialized policies, for example for specialized policies for idle sessions
 * for specific STUN usages.
 * 
 * @param  The type returned when visitors visit {@link StunMessage}s. 
 */
public class StunIoHandler extends IoHandlerAdapter {

    private final Logger m_log = LoggerFactory.getLogger(StunIoHandler.class);
    private final StunMessageVisitorFactory m_visitorFactory;
    
    /**
     * Creates a new STUN IO handler class.
     * 
     * @param visitorFactory The factory for creating visitors for the 
     * specific STUN deployment.  Some factories might create visitors for the
     * client side while others create visitors for the server side, 
     * for example.
     */
    public StunIoHandler(final StunMessageVisitorFactory visitorFactory) {
        this.m_visitorFactory = visitorFactory;
    }

    @Override
    public void messageReceived(final IoSession session, final Object message) {
        m_log.debug("Received message: {}", message);

        if (session.isClosing() || !session.isConnected()) {
            m_log.debug("Ignoring message on closing session...");
            return;
        }
        final StunMessage stunMessage = (StunMessage) message;

        // The visitor will handle the particular message type, allowing for
        // variation between, for example, client and server visitor
        // implementations.
        final StunMessageVisitor visitor = this.m_visitorFactory
                .createVisitor(session);

        m_log.debug("Sending message to visitor: {}", visitor);
        stunMessage.accept(visitor);
    }

    @Override
    public void exceptionCaught(final IoSession session, final Throwable cause) {
        m_log.debug("Exception on STUN IoHandler", cause);
        if (cause instanceof PortUnreachableException) {
            // We pretend it's like an ordinary STUN "message" and visit it.
            // We allow the processing classes to close the session as they
            // see fit.
            //
            // This will occur relatively frequently over the course of normal
            // STUN checks for UDP.
            final ConnectErrorStunMessage icmpError = new ConnectErrorStunMessage();
            messageReceived(session, icmpError);
        } else {
            m_log.warn("Exception on STUN IoHandler for session: "+session, cause);
            session.close();
        }
    }

    @Override
    public void sessionCreated(final IoSession session) throws Exception {
        SessionUtil.initialize(session);

        // The idle time is in seconds. If there's been no traffic in either
        // direction for awhile, we free the connection.
        session.setIdleTime(IdleStatus.BOTH_IDLE, 100);
    }

    @Override
    public void sessionIdle(final IoSession session, final IdleStatus status) {
        m_log.debug("Killing idle session");
        // Kill idle sessions.
        session.close();
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy