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

com.veraxsystems.vxipmi.connection.ConnectionManager Maven / Gradle / Ivy

The newest version!
/*
 * ConnectionManager.java 
 * Created on 2011-08-24
 *
 * Copyright (c) Verax Systems 2011.
 * All rights reserved.
 *
 * This software is furnished under a license. Use, duplication,
 * disclosure and all other uses are restricted to the rights
 * specified in the written license agreement.
 */
package com.veraxsystems.vxipmi.connection;

import com.veraxsystems.vxipmi.coding.commands.PrivilegeLevel;
import com.veraxsystems.vxipmi.coding.commands.session.GetChannelAuthenticationCapabilitiesResponseData;
import com.veraxsystems.vxipmi.coding.security.CipherSuite;
import com.veraxsystems.vxipmi.common.PropertiesManager;
import com.veraxsystems.vxipmi.transport.Messenger;
import com.veraxsystems.vxipmi.transport.UdpListener;
import com.veraxsystems.vxipmi.transport.UdpMessenger;

import java.io.IOException;
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * Manages multiple {@link Connection}s
 */
public class ConnectionManager {
    private Messenger messenger;
    private List connections;

    private static final AtomicInteger sessionlessTag = new AtomicInteger(0);
    private static List reservedTags = new ArrayList();

    /**
     * Frequency of the no-op commands that will be sent to keep up the session
     */
    private static int pingPeriod = -1;

    /**
     * Initiates the connection manager. Wildcard IP address will be used.
     *
     * @param port
     *            the port at which {@link UdpListener} will work
     * @throws IOException
     *             when properties file was not found
     */
    public ConnectionManager(int port) throws IOException {
        messenger = new UdpMessenger(port);
        initialize();
    }

    /**
     * Initiates the connection manager.
     *
     * @param port
     *            the port at which {@link UdpListener} will work
     * @param address
     *            the IP interface {@link UdpListener} will bind to
     * @throws IOException
     *             when properties file was not found
     */
    public ConnectionManager(int port, InetAddress address) throws IOException {
        messenger = new UdpMessenger(port, address);
        initialize();
    }

    /**
     * Initiates the connection manager.
     *
     * @param messenger
     *            {@link Messenger} to be used in communication
     */
    public ConnectionManager(Messenger messenger) {
        this.messenger = messenger;
        initialize();
    }

    private void initialize() {
        connections = new ArrayList();
        reservedTags = new ArrayList();
        if (pingPeriod == -1) {
            pingPeriod = Integer.parseInt(PropertiesManager.getInstance().getProperty("pingPeriod"));
        }
    }

    /**
     * Closes all open connections and disconnects {@link UdpListener}.
     */
    public void close() {
        synchronized (connections) {
            for (Connection connection : connections) {
                if (connection != null && connection.isActive()) {
                    connection.disconnect();
                }
            }
        }
        messenger.closeConnection();
    }

    /**
     * The tag for messages sent outside the session generated by the
     * {@link ConnectionManager}. Auto-incremented.
     */
    public static int generateSessionlessTag() {
        synchronized (sessionlessTag) {
            boolean wait = true;
            while (wait) {
                sessionlessTag.incrementAndGet();
                sessionlessTag.set(sessionlessTag.get() % 60);
                synchronized (reservedTags) {
                    if (!reservedTags.contains(sessionlessTag.get())) {
                        wait = false;
                    }
                }
                if (wait) {
                    try {
                        sessionlessTag.wait(1);
                    } catch (InterruptedException e) {
                        // TODO log
                    }
                }
            }
            synchronized (reservedTags) {
                reservedTags.add(sessionlessTag.get());
            }
            return sessionlessTag.get();
        }
    }

    /**
     * Frees the sessionless tag for further use
     *
     * @param tag
     *            - tag to free
     */
    public static void freeTag(int tag) {
        synchronized (reservedTags) {
            reservedTags.remove((Integer) tag);
        }
    }

    /**
     * Returns {@link Connection} identified by index.
     *
     * @param index
     *            - index of the connection to return
     */
    public Connection getConnection(int index) {
        return connections.get(index);
    }

    /**
     * Closes the connection with the given index.
     */
    public void closeConnection(int index) {
        connections.get(index).disconnect();
    }

    /**
     * Returns first {@link Connection} associated with the address
     *
     * @param address
     *            {@link InetAddress} of the remote host to get connection
     *            with.
     * @return First {@link Connection} to the address or null if none found
     */
    public Connection getConnection(InetAddress address, int port) {
        synchronized (connections) {
            for (Connection connection : connections) {
                if (connection != null && connection.isActive()
                        && connection.getRemoteMachineAddress() == address
                        && connection.getRemoteMachinePort() == port) {
                    return connection;
                }
            }
        }
        return null;
    }

    /**
     * Creates and initiates {@link Connection} to the remote host.
     * @param address
     * {@link InetAddress} of the remote host
     * @param pingPeriod
     * frequency of the no-op commands that will be sent to keep up the session
     * @param skipCiphers
     * determines if the getAvailableCipherSuites and getChannelAuthenticationCapabilities phases should be skipped
     * @return index of the connection
     * @throws IOException
     * when properties file was not found
     */
    public int createConnection(InetAddress address, int port, int pingPeriod, boolean skipCiphers) throws IOException {
        Connection connection = new Connection(messenger, 0);
        connection.connect(address, port, pingPeriod, skipCiphers);

        synchronized (connections) {
            connections.add(connection);
            return connections.size() - 1;
        }
    }

    /**
     * Creates and initiates {@link Connection} to the remote host.
     *
     * @param address
     *            - {@link InetAddress} of the remote host
     * @param pingPeriod
     *            - frequency of the no-op commands that will be sent to keep up
     *            the session
     * @return index of the connection
     * @throws IOException
     *             - when properties file was not found
     */
    public int createConnection(InetAddress address, int port, int pingPeriod) throws IOException {
        Connection connection = new Connection(messenger, 0);
        connection.connect(address, port, pingPeriod);

        synchronized (connections) {
            connections.add(connection);
            return connections.size() - 1;
        }
    }

    /**
     * Creates and initiates {@link Connection} to the remote host with the
     * default ping frequency.
     *
     * @param address
     *            - {@link InetAddress} of the remote host
     * @return index of the connection
     * @throws IOException
     *             when properties file was not found
     */
    public int createConnection(InetAddress address, int port) throws IOException {

        synchronized (connections) {
            Connection connection = new Connection(messenger,
                    connections.size());
            connection.connect(address, port, pingPeriod);
            connections.add(connection);
            return connections.size() - 1;
        }
    }

    /**
     * Creates and initiates {@link Connection} to the remote host with the default ping frequency.
     * @param address
     * - {@link InetAddress} of the remote host
     * @param skipCiphers
     * - determines if the getAvailableCipherSuites and getChannelAuthenticationCapabilities phases should be skipped
     * @return index of the connection
     * @throws IOException
     * when properties file was not found
     */
    public int createConnection(InetAddress address, int port, boolean skipCiphers) throws IOException {
        synchronized (connections) {
            Connection connection = new Connection(messenger, connections.size());
            connection.connect(address, port, pingPeriod, skipCiphers);
            connections.add(connection);
            return connections.size() - 1;
        }
    }

    /**
     * Gets from the managed system supported {@link CipherSuite}s. Should be
     * performed only immediately after {@link #createConnection}.
     *
     * @param connection
     *            - index of the connection to get available Cipher Suites from
     *
     * @return list of the {@link CipherSuite}s supported by the managed system.
     * @throws ConnectionException
     *             when connection is in the state that does not allow to
     *             perform this operation.
     * @throws Exception
     *             when sending message to the managed system fails
     */
    public List getAvailableCipherSuites(int connection)
            throws Exception {
        int tag = generateSessionlessTag();
        List suites;
        try {
            suites = connections.get(connection).getAvailableCipherSuites(tag);
        } catch (Exception e) {
            freeTag(tag);
            throw e;
        }
        freeTag(tag);
        return suites;
    }

    /**
     * Queries the managed system for the details of the authentification
     * process. Must be performed after {@link #getAvailableCipherSuites(int)}
     *
     * @param connection
     *            - index of the connection to get Channel Authentication
     *            Capabilities from
     * @param cipherSuite
     *            - {@link CipherSuite} requested for the session
     * @param requestedPrivilegeLevel
     *            - {@link PrivilegeLevel} requested for the session
     * @return {@link GetChannelAuthenticationCapabilitiesResponseData}
     * @throws ConnectionException
     *             when connection is in the state that does not allow to
     *             perform this operation.
     * @throws Exception
     *             when sending message to the managed system fails
     */
    public GetChannelAuthenticationCapabilitiesResponseData getChannelAuthenticationCapabilities(
            int connection, CipherSuite cipherSuite,
            PrivilegeLevel requestedPrivilegeLevel) throws Exception {
        int tag = generateSessionlessTag();
        GetChannelAuthenticationCapabilitiesResponseData responseData;
        try {
            responseData = connections.get(connection)
                    .getChannelAuthenticationCapabilities(tag, cipherSuite,
                            requestedPrivilegeLevel);
        } catch (Exception e) {
            freeTag(tag);
            throw e;
        }
        freeTag(tag);
        return responseData;
    }

    /**
     * Initiates the session with the managed system. Must be performed after
     * {@link #getChannelAuthenticationCapabilities(int, CipherSuite, PrivilegeLevel)}
     *
     * @param connection
     *            - index of the connection that starts the session
     * @param cipherSuite
     *            - {@link CipherSuite} that will be used during the session
     * @param privilegeLevel
     *            - requested {@link PrivilegeLevel} - most of the time it will
     *            be {@link PrivilegeLevel#User}
     * @param username
     *            - the username
     * @param password
     *            - the password matching the username
     * @param bmcKey
     *            - the key that should be provided if the two-key
     *            authentication is enabled, null otherwise.
     * @throws ConnectionException
     *             when connection is in the state that does not allow to
     *             perform this operation.
     * @throws Exception
     *             when sending message to the managed system or initializing
     *             one of the cipherSuite's algorithms fails
     */
    public int startSession(int connection, CipherSuite cipherSuite,
            PrivilegeLevel privilegeLevel, String username, String password,
            byte[] bmcKey) throws Exception {
        int sessionId;
        int tag = generateSessionlessTag();
        try {
            sessionId = connections.get(connection).startSession(tag, cipherSuite,
                    privilegeLevel, username, password, bmcKey);
        } catch (Exception e) {
            freeTag(tag);
            throw e;
        }
        freeTag(tag);

        return sessionId;
    }

    /**
     * Registers the listener so it will receive notifications from connection
     *
     * @param connection
     *            - index of the {@link Connection} to listen to
     * @param listener
     *            - {@link ConnectionListener} to processResponse
     */
    public void registerListener(int connection, ConnectionListener listener) {
        connections.get(connection).registerListener(listener);
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy