Package com.trendmicro.mist.session

Source Code of com.trendmicro.mist.session.Session

package com.trendmicro.mist.session;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketTimeoutException;
import java.util.Collection;
import java.util.HashMap;

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

import com.trendmicro.mist.Client;
import com.trendmicro.mist.Daemon;
import com.trendmicro.mist.MistException;
import com.trendmicro.mist.proto.GateTalk;
import com.trendmicro.mist.util.Exchange;

public abstract class Session implements Runnable {
    public static final String MIST_MESSAGE_TTL = "MIST_TTL";
    protected final static Logger logger = LoggerFactory.getLogger(Session.class);
    private ServerSocket localServer;

    protected Socket socket;
    protected BufferedInputStream socketInput;
    protected BufferedOutputStream socketOutput;
    protected volatile boolean detachNow = false;

    protected HashMap<Exchange, Client> allClients = new HashMap<Exchange, Client>();

    protected boolean determinedConnection = false;

    protected int sessionId;
    protected GateTalk.Session sessionConfig;
    protected boolean isReady = false;
    protected Thread sessionThread = null;
    private Object attachLock = new Object();

    /**
     * Helper function to accept an incoming connection from the client. The
     * localServer is used one time only and will not accept more then one
     * connection.
     *
     * @return True - If the connection and the socket IO streams has been set
     *         up correctly<br>
     *         False - Fail to accept the connection or session is detached
     */
    protected boolean acceptConnection() {
        socket = null;
        socketInput = null;
        socketOutput = null;
        try {
            for(int i = 0; i < 60; i++) {
                try {
                    socket = localServer.accept();
                    localServer.close();
                    localServer = null;
                    break;
                }
                catch(SocketTimeoutException e) {
                    if(detachNow) {
                        cleanupSockets();
                        return false;
                    }
                }
            }
            if(socket == null) {
                throw new IOException("cannot accept client connection (timed out)");
            }
            socket.setTcpNoDelay(true);
            socketInput = new BufferedInputStream(socket.getInputStream());
            socketOutput = new BufferedOutputStream(socket.getOutputStream());
            return true;
        }
        catch(IOException e) {
            cleanupSockets();
            return false;
        }
    }

    /**
     * Helper function to clean up the sockets
     */
    private void cleanupSockets() {
        if(localServer != null) {
            try {
                localServer.close();
            }
            catch(Exception e) {
            }
        }
        if(socketOutput != null) {
            try {
                socketOutput.close();
            }
            catch(Exception e) {
            }
        }
        if(socketInput != null) {
            try {
                socketInput.close();
            }
            catch(Exception e) {
            }
        }
        if(socket != null) {
            try {
                socket.close();
            }
            catch(Exception e) {
            }
        }
    }

    private void checkRole(GateTalk.Request.Role role) throws MistException {
        if(this instanceof ProducerSession) {
            if(role == GateTalk.Request.Role.SOURCE)
                throw new MistException(MistException.INCOMPATIBLE_TYPE_SINK);
        }
        else {
            if(role == GateTalk.Request.Role.SINK)
                throw new MistException(MistException.INCOMPATIBLE_TYPE_SOURCE);
        }
    }

    public Session(int sessId, GateTalk.Session sessConfig) throws MistException {
        this.sessionId = sessId;
        this.sessionConfig = sessConfig;
    }

    public int getCommPort() {
        if(localServer == null)
            return -1;
        else
            return localServer.getLocalPort();
    }

    @Override
    public abstract void run();

    public abstract void addClientIfAttached(Client c);

    /**
     * All clients under this session will be opened
     *
     * @param isResume
     */
    public void open(boolean isResume) {
        for(Client c : allClients.values()) {
            try {
                c.openClient(determinedConnection, isResume, false);
            }
            catch(Exception e) {
                logger.error(e.getMessage());
            }
        }
    }

    /**
     * All clients under this session will be opened
     *
     * @param isPause
     */
    public void close(final boolean isPause) {
        // A consumer thread is not allowed to close jms session, so fork a
        // thread here to close them
        Thread closingThread = new Thread() {
            @Override
            public void run() {
                setName(sessionId + "-closer");
                for(Client c : allClients.values()) {
                    c.closeClient(isPause, false);
                }
                detachNow = false;
                synchronized(Daemon.closingThreadSet) {
                    Daemon.closingThreadSet.remove(this);
                }
            }
        };
        closingThread.start();
        synchronized(Daemon.closingThreadSet) {
            Daemon.closingThreadSet.add(closingThread);
        }
    }

    /**
     * Create a server socket and starts a serving thread
     *
     * @param role
     *            Whether it is a SOURCE or a SINK
     * @throws MistException
     */
    public void attach(GateTalk.Request.Role role) throws MistException {
        checkRole(role);
        while(detachNow) {
            try {
                Thread.sleep(100);
            }
            catch(InterruptedException e) {
                return;
            }
        }

        synchronized(attachLock) {
            if(isAttached())
                throw new MistException(MistException.ALREADY_ATTACHED);
           
            try {
                localServer = new ServerSocket();
                localServer.setReuseAddress(true);
                localServer.setSoTimeout(1000);
                localServer.bind(null);
            }
            catch(IOException e) {
                logger.error(e.getMessage());
                try {
                    localServer.close();
                }
                catch(Exception e2) {
                }
                throw new MistException(e.getMessage());
            }
            detachNow = false;
            isReady = false;

            sessionThread = new Thread(this);
            sessionThread.setName("Session-" + sessionId);
            sessionThread.start();
        }
    }

    protected abstract void detach();

    public void detach(GateTalk.Request.Role role) throws MistException {
        checkRole(role);

        synchronized(attachLock) {
            detachNow = true;
            detach();
            close(false);
            cleanupSockets();
            try {
                sessionThread.join();
            }
            catch(Exception e) {
            }
        }
    }

    /**
     * Add a producer / consumer client to the session
     *
     * @param client
     *            The client to be added
     * @throws MistException
     */
    public Client addClient(GateTalk.Client clientConfig) throws MistException {
        // A producer client cannot be added to a source session and vice versa
        checkRole(clientConfig.getType() == GateTalk.Client.Type.CONSUMER ? GateTalk.Request.Role.SOURCE: GateTalk.Request.Role.SINK);

        synchronized(allClients) {
            // Check if the client is already mounted, if not, add to the map
            if(allClients.containsKey(new Exchange(clientConfig.getChannel().getName())))
                throw new MistException(MistException.ALREADY_MOUNTED);

            Client c = new Client(clientConfig, sessionConfig);
            if(isAttached()){
                c.openClient(determinedConnection, false, false);
                addClientIfAttached(c);
            }
            allClients.put(c.getExchange(), c);
            return c;
        }
    }

    public void removeClient(GateTalk.Client clientConfig) throws MistException {
        checkRole(clientConfig.getType() == GateTalk.Client.Type.CONSUMER ? GateTalk.Request.Role.SOURCE: GateTalk.Request.Role.SINK);

        synchronized(allClients) {
            if(allClients.isEmpty())
                throw new MistException(MistException.EMPTY_SESSION);

            Exchange exchange = new Exchange((clientConfig.getChannel().getType() == GateTalk.Channel.Type.QUEUE ? "queue": "topic") + ":" + clientConfig.getChannel().getName());
            Client c = findClient(exchange);
            if(c == null)
                throw new MistException(MistException.exchangeNotFound(exchange.toString()));
            c.closeClient(false, false);
            allClients.remove(exchange);
        }
    }

    public void migrateClient(Exchange exchange) {
        logger.info("migrating " + exchange + "; session " + sessionId);
        try {
            GateTalk.Client clientConfig = findClient(exchange).getConfig();
            removeClient(findClient(exchange).getConfig());
            addClient(clientConfig);
        }
        catch(Exception e) {
            logger.error(e.getMessage(), e);
        }
    }

    public Client findClient(Exchange exchange) {
        return allClients.get(exchange);
    }

    public boolean isReady() {
        return isReady;
    }

    public abstract boolean isAttached();

    public Collection<Client> getClientList() {
        return allClients.values();
    }
}
TOP

Related Classes of com.trendmicro.mist.session.Session

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.