/**
* 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 <COPYRIGHT HOLDER> 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.parser.text;
import org.jscsi.exception.InternetSCSIException;
import org.jscsi.parser.Constants;
import org.jscsi.parser.InitiatorMessageParser;
import org.jscsi.parser.ProtocolDataUnit;
import org.jscsi.parser.datasegment.DataSegmentFactory.DataSegmentFormat;
import org.jscsi.utils.Utils;
/**
* <h1>TextRequestParser</h1>
* <p>
* This class parses a Text Request message defined in the iSCSI Standard (RFC3720).
*
* @author Volker Wildi
*/
public final class TextRequestParser extends InitiatorMessageParser {
// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
/** Continue Flag. */
private boolean continueFlag;
/** Target Transfer Tag. */
private int targetTransferTag;
// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
/**
* Default constructor, creates a new, empty <code>TextRequestParser</code> object.
*
* @param initProtocolDataUnit
* The reference <code>ProtocolDataUnit</code> instance, which
* contains this <code>TextRequestParser</code> subclass object.
*/
public TextRequestParser(final ProtocolDataUnit initProtocolDataUnit) {
super(initProtocolDataUnit);
}
// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
/** {@inheritDoc} */
@Override
public final String toString() {
final StringBuilder sb = new StringBuilder(Constants.LOG_INITIAL_SIZE);
Utils.printField(sb, "Continue Flag", continueFlag, 1);
Utils.printField(sb, "LUN", logicalUnitNumber, 1);
Utils.printField(sb, "Target Transfer Tag", targetTransferTag, 1);
sb.append(super.toString());
return sb.toString();
}
/** {@inheritDoc} */
@Override
public final DataSegmentFormat getDataSegmentFormat() {
return DataSegmentFormat.TEXT;
}
/** {@inheritDoc} */
@Override
public final void clear() {
super.clear();
continueFlag = false;
targetTransferTag = 0x00000000;
}
// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
/**
* Sets the Target Transfer Tag to a new one.
*
* @param newTargetTransferTag
* The new Target Transfer Tag.
* @see #getTargetTransferTag()
*/
public final void setTargetTransferTag(final int newTargetTransferTag) {
targetTransferTag = newTargetTransferTag;
}
// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
/**
* When set to <code>1</code>, indicates that the text (set of key=value
* pairs) in this Text Request is not complete (it will be continued on
* subsequent Text Requests); otherwise, it indicates that this Text Request
* ends a set of key=value pairs. A Text Request with the <code>C</code> bit
* set to <code>1</code> MUST have the F bit set to <code>0</code>.
*
* @return <code>True</code>, if the Continue Flag is set. Else <code>false</code>.
*/
public final boolean isContinueFlag() {
return continueFlag;
}
/**
* When the <em>Target Transfer Tag</em> is set to the reserved value <code>0xffffffff</code>, it tells
* the target that this is a new request
* and the target resets any internal state associated with the Initiator
* Task Tag (resets the current negotiation state). The target sets the
* Target Transfer Tag in a text response to a value other than the reserved
* value <code>0xffffffff</code> whenever it indicates that it has more data
* to send or more operations to perform that are associated with the
* specified Initiator Task Tag. It MUST do so whenever it sets the <code>F</code> bit to <code>0</code>
* in the response. By copying the
* Target Transfer Tag from the response to the next Text Request, the
* initiator tells the target to continue the operation for the specific
* Initiator Task Tag. The initiator MUST ignore the Target Transfer Tag in
* the Text Response when the <code>F</code> bit is set to <code>1</code>.
* This mechanism allows the initiator and target to transfer a large amount
* of textual data over a sequence of text-command/text-response exchanges,
* or to perform extended negotiation sequences. If the Target Transfer Tag
* is not <code>0xffffffff</code>, the <code>LUN</code> field MUST be sent
* by the target in the Text Response.
* <p>
* A target MAY reset its internal negotiation state if an exchange is stalled by the initiator for a long
* time or if it is running out of resources. Long text responses are handled as in the following example:
* I->T Text SendTargets=All (F=1,TTT=0xffffffff) T->I Text <part 1> (F=0,TTT=0x12345678) I->T Text
* <empty> (F=1, TTT=0x12345678) T->I Text <part 2> (F=0, TTT=0x12345678) I->T Text
* <empty> (F=1, TTT=0x12345678) ... T->I Text <part n> (F=1, TTT=0xffffffff)
*
* @return The <em>Target Transfer Tag</em> of this <code>TextRequestParser</code> object.
*/
public final int getTargetTransferTag() {
return targetTransferTag;
}
// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
/** {@inheritDoc} */
@Override
protected final void deserializeBytes1to3(final int line) throws InternetSCSIException {
continueFlag = Utils.isBitSet(line & Constants.CONTINUE_FLAG_MASK);
Utils.isReserved(line & ~Constants.CONTINUE_FLAG_MASK);
}
/** {@inheritDoc} */
@Override
protected final void deserializeBytes20to23(final int line) throws InternetSCSIException {
targetTransferTag = line;
}
// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
/** {@inheritDoc} */
@Override
protected final void checkIntegrity() throws InternetSCSIException {
String exceptionMessage;
do {
if (protocolDataUnit.getBasicHeaderSegment().isFinalFlag() && continueFlag) {
exceptionMessage = "Final and Continue Flag cannot be set at the same time.";
break;
}
// message is checked correctly
return;
} while (false);
throw new InternetSCSIException(exceptionMessage);
}
// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
/** {@inheritDoc} */
@Override
protected final int serializeBytes1to3() {
int line = 0;
if (continueFlag) {
line |= Constants.CONTINUE_FLAG_MASK;
}
return line;
}
/** {@inheritDoc} */
@Override
protected final int serializeBytes20to23() {
return targetTransferTag;
}
// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
}