Package de.fhkn.in.uce.relaying.server

Source Code of de.fhkn.in.uce.relaying.server.RefreshMessageHandlerTask

/*
* 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.relaying.server;

import java.io.IOException;
import java.net.Socket;
import java.net.SocketTimeoutException;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import de.fhkn.in.uce.core.socketlistener.SocketListener;
import de.fhkn.in.uce.relaying.message.RelayingAttributeTypeDecoder;
import de.fhkn.in.uce.relaying.message.RelayingConstants;
import de.fhkn.in.uce.relaying.message.RelayingLifetime;
import de.fhkn.in.uce.stun.attribute.ErrorCode.STUNErrorCode;
import de.fhkn.in.uce.stun.header.STUNMessageMethod;
import de.fhkn.in.uce.stun.message.Message;
import de.fhkn.in.uce.stun.message.MessageReader;
import de.fhkn.in.uce.stun.message.MessageWriter;

/**
* Task that handles refresh messages of client.
*
* @author thomas zink, daniel maier, Alexander Diener
*         (aldiener@htwg-konstanz.de)
*
*/
public final class RefreshMessageHandlerTask implements Runnable {
    private static final Logger logger = LoggerFactory.getLogger(RefreshMessageHandlerTask.class);

    private final Socket controlConnection;
    private final MessageWriter controlConnectionWriter;
    private final int initRefreshInterval;
    private final Thread peerListener;

    /**
     * Creates a new {@link RefreshMessageHandlerTask}.
     *
     * @param controlConnection
     *            control connection to the client
     * @param controlConnectionWriter
     *            a {@link MessageWriter} to the control connection
     * @param lifetime
     *            the lifetime of the control connection without refresh
     *            messages. If lifetime is 0,
     *            {@link Constants#DEFAULT_ALLOCATION_REFRESH_INTERVAL} is used.
     *            If lifetime is greater than
     *            {@link Constants#ALLOCATION_LIFETIME_MAX},
     *            {@link Constants#ALLOCATION_LIFETIME_MAX} is used.
     * @param peerListener
     *            listener thread that waits for peer connections to the
     *            relevant client
     */
    public RefreshMessageHandlerTask(Socket controlConnection, MessageWriter controlConnectionWriter, int lifetime,
            SocketListener peerListener) {
        this.controlConnection = controlConnection;
        this.controlConnectionWriter = controlConnectionWriter;
        this.peerListener = peerListener;
        if (lifetime == 0) {
            this.initRefreshInterval = RelayingConstants.DEFAULT_ALLOCATION_REFRESH_INTERVAL;
        } else {
            this.initRefreshInterval = (lifetime < RelayingConstants.ALLOCATION_LIFETIME_MAX) ? lifetime
                    : RelayingConstants.ALLOCATION_LIFETIME_MAX;
        }
    }

    /**
     * Waits for refresh messages from the client. If no refresh message arrives
     * during the specified lifetime, the task gets stopped and the given
     * listener thread for peer connections gets stopped too. Moreover if
     * lifetime of a refresh message is equal or less than 0, the task and the
     * listener thread get stopped.
     */
    private void handle() {
        int refreshInterval = initRefreshInterval;
        try {
            while (true) {
                controlConnection.setSoTimeout(refreshInterval * 1000);
                final MessageReader messageReader = this.createCustomRelayingMessageReader();
                final Message message = messageReader.readSTUNMessage(controlConnection.getInputStream());
                // check if it is refresh message (atm the only one that is
                // allowed)
                if (message == null) {
                    // connection closed
                    logger.error("Received message was null");
                    break;
                }
                if (message.isMethod(STUNMessageMethod.KEEP_ALIVE) && message.isRequest()) {
                    int lifetime = message.getAttribute(RelayingLifetime.class).getLifeTime();
                    logger.info("Received refresh request with lifetime {}", lifetime);
                    if (lifetime > 0) {
                        refreshInterval = (lifetime < RelayingConstants.ALLOCATION_LIFETIME_MAX) ? lifetime
                                : RelayingConstants.ALLOCATION_LIFETIME_MAX;
                        // send refresh response
                        Message successResponse = message.buildSuccessResponse();
                        successResponse.addAttribute(new RelayingLifetime(refreshInterval));
                        controlConnectionWriter.writeMessage(successResponse);
                    } else {
                        // send refresh response (unallocate)
                        Message successResponse = message.buildSuccessResponse();
                        successResponse.addAttribute(new RelayingLifetime(0));
                        controlConnectionWriter.writeMessage(successResponse);
                        break;
                    }
                } else {
                    logger.error("Received unexpected message: {}", message.getMessageMethod());
                    Message errorResponse = message.buildFailureResponse(STUNErrorCode.BAD_REQUEST,
                            "Expected refresh request");
                    controlConnectionWriter.writeMessage(errorResponse);
                }
            }
        } catch (SocketTimeoutException e) {
            logger.info("No refresh request within specified timeout. Closing control conection and "
                    + "destroy allocation");
        } catch (IOException e) {
            logger.error("IOException while reading from control connection. Closing control "
                    + "conection and destroy allocation");
            e.printStackTrace();
        } finally {
            // something went wrong -> destroy allocation
            peerListener.interrupt();
            try {
                controlConnection.close();
            } catch (IOException ignore) {
            }
        }

    }

    public void run() {
        handle();
    }

    private MessageReader createCustomRelayingMessageReader() {
        return MessageReader.createMessageReaderWithCustomAttributeTypeDecoder(new RelayingAttributeTypeDecoder());
    }
}
TOP

Related Classes of de.fhkn.in.uce.relaying.server.RefreshMessageHandlerTask

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.