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

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

The newest version!
/*
 * MessageHandler.java
 * Created on 23.05.2017
 *
 * Copyright (c) Sonalake 2017.
 * 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.PayloadCoder;
import com.veraxsystems.vxipmi.coding.protocol.Ipmiv20Message;
import com.veraxsystems.vxipmi.connection.queue.MessageQueue;
import com.veraxsystems.vxipmi.sm.StateMachine;
import com.veraxsystems.vxipmi.sm.events.Sendv20Message;
import com.veraxsystems.vxipmi.sm.states.SessionValid;
import org.apache.log4j.Logger;

/**
 * Class used for handling outgoing and incoming messages for a {@link Connection}.
 */
public abstract class MessageHandler {

    private static final Logger logger = Logger.getLogger(MessageHandler.class);

    protected int lastReceivedSequenceNumber = 0;
    protected final MessageQueue messageQueue;
    protected final Connection connection;

    public MessageHandler(Connection connection, int timeout, int minSequenceNumber, int maxSequenceNumber) {
        this.messageQueue = new MessageQueue(connection, timeout, minSequenceNumber, maxSequenceNumber);
        this.connection = connection;
    }

    /**
     * Attempts to send message encoded by given {@link PayloadCoder} to the remote system.
     *
     * @param payloadCoder
     *          instance of {@link PayloadCoder} that will produce payload for the message being sent.
     * @param stateMachine
     *          {@link StateMachine} for the currenr connection.
     * @param sessionId
     *          ID of the current session.
     * @param isOneWay
     *          flag indicating, if message is one way and we shouldn't await response,
     *          or it isn't and needs response from remote system
     * @return sequence number of the sent message
     * @throws ConnectionException when could not send message due to some problems with connection
     */
    public int sendMessage(PayloadCoder payloadCoder, StateMachine stateMachine, int sessionId, boolean isOneWay)
            throws ConnectionException {
        validateSessionState(stateMachine);

        int seq = isOneWay ? messageQueue.getSequenceNumber() : messageQueue.add(payloadCoder);
        if (seq > 0) {
            stateMachine.doTransition(new Sendv20Message(payloadCoder, sessionId, seq, connection.getNextSessionSequenceNumber()));
        }

        return seq;
    }

    /**
     * Attempts to retry sending message with given tag, assuming that this message exists in message queue.
     *
     * @param tag
     *          tag of the message that we want to resend
     * @param stateMachine
     *          {@link StateMachine} for the currenr connection.
     * @param sessionId
     *          ID of the current session.
     * @return sequence number of the retried message (should be the same as original message tag) or -1 if no message was found in the queue.
     * @throws ConnectionException when could not send message due to some problems with connection
     */
    public int retryMessage(int tag, StateMachine stateMachine, int sessionId) throws ConnectionException {
        validateSessionState(stateMachine);

        PayloadCoder payloadCoder = messageQueue.getMessageFromQueue(tag);

        if (payloadCoder == null) {
            return  -1;
        }

        stateMachine.doTransition(new Sendv20Message(payloadCoder, sessionId, tag, connection.getNextSessionSequenceNumber()));

        return tag;
    }

    private void validateSessionState(StateMachine stateMachine) throws ConnectionException {
        if (stateMachine.getCurrent().getClass() != SessionValid.class) {
            throw new ConnectionException("Illegal connection state: " + stateMachine.getCurrent().getClass().getSimpleName());
        }
    }

    /**
     * Checks if received message is inside "sliding window range", and if it is,
     * further processes the message in a cimplementation-specific way.
     *
     * @param message
     */
    public void handleIncomingMessage(Ipmiv20Message message) {

        int seq = message.getSessionSequenceNumber();

        if (seq != 0 && (seq > lastReceivedSequenceNumber + 15 || seq < lastReceivedSequenceNumber - 16)) {
            logger.debug("Dropping message " + seq);
            return; // if the message's sequence number gets out of the sliding
            // window range we need to drop it
        }

        if (seq != 0) {
            lastReceivedSequenceNumber = (seq > lastReceivedSequenceNumber ? seq : lastReceivedSequenceNumber);
        }

        handleIncomingMessageInternal(message);
    }

    public void setTimeout(int timeout) {
        messageQueue.setTimeout(timeout);
    }

    public void tearDown() {
        messageQueue.tearDown();
    }

    public int getSequenceNumber() {
        return messageQueue.getSequenceNumber();
    }

    /**
     * Abstract method for implementation-specific logic for handling incomming IPMI message.
     *
     * @param message
     *          IPMI message received from BMC
     */
    protected abstract void handleIncomingMessageInternal(Ipmiv20Message message);

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy