
org.jscsi.initiator.connection.Connection Maven / Gradle / Ivy
/**
* Copyright (c) 2012, University of Konstanz, Distributed Systems Group
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the University of Konstanz nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.jscsi.initiator.connection;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.security.DigestException;
import java.util.Queue;
import org.jscsi.exception.InternetSCSIException;
import org.jscsi.exception.NoSuchSessionException;
import org.jscsi.exception.OperationalTextKeyException;
import org.jscsi.initiator.Configuration;
import org.jscsi.initiator.connection.state.IState;
import org.jscsi.parser.ProtocolDataUnit;
import org.jscsi.parser.datasegment.OperationalTextKey;
import org.jscsi.parser.datasegment.SettingsMap;
import org.jscsi.utils.SerialArithmeticNumber;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* AbsConnection
*
* This abstract class represents a connection, which is used in the iSCSI Standard (RFC3720). Such a
* connection is directed from the initiator to the target. It is used in Sessions.
*
* @author Volker Wildi, University of Konstanz
* @author Patrice Matthias Brend'amour, University of Konstanz
* @author Sebastian Graf, University of Konstanz
*/
public final class Connection {
// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
/** The logger interface. */
private static final Logger LOGGER = LoggerFactory.getLogger(Connection.class);
// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
/**
* The Session
instance, which contains this Connection
instance.
*/
private final Session referenceSession;
/** The Configuration
instance for this connection. */
private final Configuration configuration;
/** The current state of this connection. */
private IState state;
/**
* The ID of this connection. This must be unique within a Session
.
*/
private final short connectionID;
/**
* The Expected Status Sequence Number, which is expected to received from
* the target within this connection.
*/
private final SerialArithmeticNumber expectedStatusSequenceNumber;
// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
/**
* The worker caller, which handles the transmission of the packages over
* the network.
*/
private final SenderWorker senderReceiver;
/**
* Method to create and return a new, empty Connection
object
* with the configured layer of threading.
*
* @param session
* Reference to the AbsSession
object, which
* contains this connection.
* @param initConfiguration
* The configuration to use within this connection.
* @param inetAddress
* The InetSocketAddress
to which this connection
* should established.
* @param initConnectionID
* The ID of this connection.
* @throws Exception
* If any error occurs.
*/
public Connection(final Session session, final Configuration initConfiguration,
final InetSocketAddress inetAddress, final short initConnectionID) throws Exception {
senderReceiver = new SenderWorker(this, inetAddress);
configuration = initConfiguration;
connectionID = initConnectionID;
referenceSession = session;
expectedStatusSequenceNumber = new SerialArithmeticNumber();
}
/**
* Updates all entries of the given response key-values with the stored
* settings of this instance.
*
* @param response
* The settings of the response.
* @throws NoSuchSessionException
* if a session with this target name is not open.
*/
public final void update(final SettingsMap response) throws NoSuchSessionException {
configuration.update(referenceSession.getTargetName(), connectionID, response);
}
/**
* Returns the value of the given parameter, which is parsed to an boolean
.
*
* @param textKey
* The name of the parameter.
* @return The boolean
value of this parameter. So if the value
* is equal to Yes
, then true
will be
* returned. Else false
is returned.
* @throws OperationalTextKeyException
* If the given parameter cannot be found.
*/
public final boolean getSettingAsBoolean(final OperationalTextKey textKey)
throws OperationalTextKeyException {
return getSetting(textKey).compareTo("Yes") == 0;
}
/**
* Returns the value of the given parameter, which is parsed to an integer
.
*
* @param textKey
* The name of the parameter.
* @return The integer
value of this parameter.
* @throws OperationalTextKeyException
* If the given parameter cannot be found.
*/
public final int getSettingAsInt(final OperationalTextKey textKey) throws OperationalTextKeyException {
return Integer.parseInt(getSetting(textKey));
}
/**
* Returns the value of the given parameter as String
.
*
* @param textKey
* The name of the parameter.
* @return The value of this parameter.
* @throws OperationalTextKeyException
* If the given parameter cannot be found.
*/
public final String getSetting(final OperationalTextKey textKey) throws OperationalTextKeyException {
return configuration.getSetting(referenceSession.getTargetName(), connectionID, textKey);
}
/**
* Returns the settings of the given session and connection.
*
* @return The settings of this specific connection.
*/
public final SettingsMap getSettings() {
return configuration.getSettings(referenceSession.getTargetName(), connectionID);
}
// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
/**
* Increments the Expected Status Sequence Number as defined in RFC1982
* where SERIAL_BITS = 32
.
*/
public final void incrementExpectedStatusSequenceNumber() {
expectedStatusSequenceNumber.increment();
}
/**
* Returns the Expected Status Sequence Number of this Connection
object.
*
* @return The current Expected Status Sequence Number.
*/
public final SerialArithmeticNumber getExpectedStatusSequenceNumber() {
return expectedStatusSequenceNumber;
}
/**
* Sets the expected Status Sequence Number to the given one from the
* leading Login Response.
*
* @param newExpectedStatusSequenceNumber
* The new value.
*/
public final void setExpectedStatusSequenceNumber(final int newExpectedStatusSequenceNumber) {
expectedStatusSequenceNumber.setValue(newExpectedStatusSequenceNumber);
LOGGER.trace("Set ExpStatSN to " + expectedStatusSequenceNumber);
}
// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
/**
* Switch to the new state. Start point of the state pattern. All states are
* computed one after another.
*
* @param newState
* The new state.
* @throws InternetSCSIException
* of any kind
*/
public final void nextState(final IState newState) throws InternetSCSIException {
this.state = newState;
if (this.state != null) {
do {
this.state.execute();
LOGGER.info("State is following: " + this.state.nextStateFollowing());
} while (this.state.nextStateFollowing());
}
}
/**
* Returns the current state of this connection.
*
* @return The current IState
instance of this Connection
instance.
*/
public final IState getState() {
return state;
}
/**
* Returns the session, which contains this connection instance.
*
* @return The parent session instance.
*/
public final Session getSession() {
return referenceSession;
}
/**
* Returns the ID of this Connection
object.
*
* @return The connection ID.
*/
public final short getConnectionID() {
return connectionID;
}
// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
/**
* This method does all the necessary steps, which are needed when a
* connection should be closed.
*
* @throws IOException
* if an I/O error occurs.
*/
public final void close() throws IOException {
senderReceiver.close();
LOGGER.debug("Connection with ID " + connectionID + " closed.");
}
/**
* Enqueue this protocol data unit to the end of the sending queue.
*
* @param protocolDataUnit
* The protocol data unit to add.
* @throws InternetSCSIException
* for nearly everything
*/
public final void send(final ProtocolDataUnit protocolDataUnit) throws InternetSCSIException {
try {
senderReceiver.sendOverWire(protocolDataUnit);
} catch (IOException e) {
throw new InternetSCSIException(e);
} catch (InterruptedException e) {
throw new InternetSCSIException(e);
}
}
/**
* Enqueue all protocol data units to the end of the sending queue.
*
* @param protocolDataUnits
* The list with all protocol data units to add.
* @throws InternetSCSIException
* for nearly everything
*/
public final void send(final Queue protocolDataUnits) throws InternetSCSIException {
for (final ProtocolDataUnit unit : protocolDataUnits) {
send(unit);
}
}
/**
* Reads one ProtocolDataUnit
instance from the receivingQueue
.
*
* @return An instance of a ProtocolDataUnit
.
* @throws InternetSCSIException
* for nearly everything
*/
public final ProtocolDataUnit receive() throws InternetSCSIException {
try {
return senderReceiver.receiveFromWire();
} catch (DigestException e) {
throw new InternetSCSIException(e);
} catch (IOException e) {
throw new InternetSCSIException(e);
}
}
// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy