1 package org.jscsi.target.settings.entry; 2 3 4 import org.jscsi.target.TargetServer; 5 import org.jscsi.target.settings.KeySet; 6 import org.jscsi.target.settings.NegotiationStatus; 7 import org.jscsi.target.settings.NegotiationType; 8 import org.jscsi.target.settings.NumericalValueRange; 9 import org.jscsi.target.settings.SingleNumericalValue; 10 11 12 /** 13 * An {@link Entry} sub-class used for negotiating integer parameters which require the iSCSI initiator to offer an 14 * interval from which the target must choose the final value. Thereby the <i>key=value</i> format differs from that 15 * required by the {@link NumericalEntry} class, for which <i>value</i> is a single integer. The <i>value</i> part 16 * expected by this class looks like <code>1024~2048</code>, however the response <i>value</i> will again be a single 17 * integer from the given range. 18 * <p> 19 * Currently this {@link Entry} sub-class is only used for two parameters - <code>IFMarkInt</code> and 20 * <code>OFMarkInt</code>. However, since the jSCSI Target does not support stream markers ( <code>IFMarker=No</code> 21 * and <code>OFMarker=No</code>), the correct response value to <code>IFMarkInt</code> and <code>OFMarkInt</code> 22 * <i>keys</i> must be <code>Irrelevant</code>. This behavior is part of the 23 * {@link Entry#negotiate(org.jscsi.target.TargetServer, org.jscsi.parser.login.LoginStage, boolean, boolean, String, String, java.util.Collection)} 24 * method, which will lead to correct responses without having to check for additional constraints (the presence and 25 * <i>value</i> of <code>IFMarker</code> and <code>OFMarker</code> <i>key=value</i> pairs. 26 * 27 * @author Andreas Ergenzinger 28 */ 29 public final class NumericalRangeEntry extends Entry { 30 31 /** 32 * A {@link NumericalValueRange} specifying the boundaries into which any RFC-conform <i>value</i> range proposed by 33 * the iSCSI initiator must fall. 34 */ 35 private final NumericalValueRange protocolValueRange; 36 37 /** 38 * This value will be the negotiation result, if it falls into the <i>value</i> range proposed by the iSCSI 39 * initiator. 40 */ 41 private final int negotiationValue; 42 43 /** 44 * The {@link NumericalRangeEntry} constructor. 45 * 46 * @param keySet contains all relevant keys 47 * @param use determines under which circumstances the parameter may be negotiated 48 * @param negotiationStatus indicates whether there is a default value or if the parameter must be negotiated 49 * @param negotiationValue the value the jSCSI Target would like to use 50 * @param protocolValueRange specifies the boundaries into which any RFC-conform <i>value</i> range proposed by the 51 * iSCSI initiator must fall 52 * @param defaultValue the default value or <code>null</code> 53 */ 54 public NumericalRangeEntry (final KeySet keySet, final Use use, final NegotiationStatus negotiationStatus, final int negotiationValue, final NumericalValueRange protocolValueRange, final Object defaultValue) { 55 super(keySet, NegotiationType.NEGOTIATED, use, negotiationStatus, defaultValue); 56 this.negotiationValue = negotiationValue; 57 this.protocolValueRange = protocolValueRange; 58 } 59 60 @Override 61 protected boolean inProtocolValueRange (Object values) { 62 // receives a NumericalValueRange 63 return protocolValueRange.contains((NumericalValueRange) values); 64 } 65 66 @Override 67 protected Object parseOffer (TargetServer target, String values) { 68 // expected format: "1234~5678" 69 70 NumericalValueRange range = NumericalValueRange.parseNumericalValueRange(values); 71 if (range == null && target.getConfig().getAllowSloppyNegotiation()) { 72 /* 73 * The format was violated. The jSCSI Initiator sends "IFMarkInt=2048" and "OFMarkInt=2048", not ranges. If 74 * values is at least a number we will fix this. 75 */ 76 final SingleNumericalValue singleValue = SingleNumericalValue.parseSingleNumericValue(values); 77 if (singleValue != null) { 78 range = NumericalValueRange.create(singleValue.getValue(),// min 79 singleValue.getValue());// max 80 } 81 } 82 83 return range; 84 } 85 86 @Override 87 protected void processDeclaration (Object values) { 88 // there are no declarations, see constructor 89 } 90 91 @Override 92 protected String processNegotiation (Object values) { 93 // receives a NumericalValueRange 94 final NumericalValueRange range = (NumericalValueRange) values; 95 // accept if negotiatedValue in initiator offer, else reject 96 if (range.contains(negotiationValue)) { 97 value = negotiationValue; 98 return value.toString(); 99 } // else 100 value = null; 101 return null; 102 } 103 104 @Override 105 public Integer getIntegerValue () { 106 return (Integer) value; 107 } 108 109 @Override 110 public Entry copy () { 111 final NumericalRangeEntry e = new NumericalRangeEntry(keySet, use, negotiationStatus, negotiationValue, protocolValueRange, (Integer) value); 112 e.alreadyNegotiated = this.alreadyNegotiated; 113 return e; 114 } 115 }