View Javadoc

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 }