View Javadoc

1   package org.jscsi.target.connection.stage.fullfeature;
2   
3   
4   import java.io.IOException;
5   import java.nio.ByteBuffer;
6   import java.security.DigestException;
7   
8   import org.jscsi.exception.InternetSCSIException;
9   import org.jscsi.parser.BasicHeaderSegment;
10  import org.jscsi.parser.ProtocolDataUnit;
11  import org.jscsi.parser.nop.NOPOutParser;
12  import org.jscsi.target.connection.TargetPduFactory;
13  import org.jscsi.target.connection.phase.TargetFullFeaturePhase;
14  import org.jscsi.target.settings.SettingsException;
15  
16  
17  /**
18   * A stage for processing NOP-Out PDUs, which are used by the initiator for pinging the target, making sure that the
19   * connection is still up.
20   * <p>
21   * The {@link #execute(ProtocolDataUnit)} method will process these ping messages and send a NOP-In PDU as ping echo,
22   * containing a copy of the NOP-Out PDU's data segment.
23   * <p>
24   * If either the NOP-OUT PDU's initiator or target transfer tag equals the reserved value of 0xffffffff, then no reply
25   * will be sent, since the PDU is only supposed to acknowledge a changed ExpCmdSN, or serve as an echo to a NOP-IN ping
26   * sent by the target.
27   * 
28   * @author Andreas Ergenzinger
29   */
30  public class PingStage extends TargetFullFeatureStage {
31  
32      private static final int RESERVED_TAG_VALUE = 0xffffffff;
33  
34      public PingStage (TargetFullFeaturePhase targetFullFeaturePhase) {
35          super(targetFullFeaturePhase);
36      }
37  
38      @Override
39      public void execute (final ProtocolDataUnit pdu) throws IOException , InterruptedException , InternetSCSIException , DigestException , SettingsException {
40  
41          final BasicHeaderSegment bhs = pdu.getBasicHeaderSegment();
42          final NOPOutParser parser = (NOPOutParser) bhs.getParser();
43  
44          if (parser.getTargetTransferTag() != RESERVED_TAG_VALUE) {
45              /*
46               * This is an error. The jSCSI Target does not send NOP-In ping messages, which would be the only legal
47               * reason for the initiator sending a NOP-Out with the TargetTransferTag equal to 0xffffffff. And even if
48               * the jSCSI Target was sending pings, the echo would be processed in a dedicated stage. Therefore, we treat
49               * this as an error. Close the connection.
50               */
51              throw new InternetSCSIException("NOP-Out PDU TargetTransferTag = " + parser.getTargetTransferTag() + " in PingStage");
52          }
53  
54          // decide whether or not response is necessary
55          if (bhs.getInitiatorTaskTag() == RESERVED_TAG_VALUE) return;// send no response
56  
57          // else
58          // prepare response data segment (copy up to initiator's
59          // MaxRecvDataSegmentLength)
60          final int dataSegmentLength = Math.min(pdu.getDataSegment().capacity(), settings.getMaxRecvDataSegmentLength());
61          final ByteBuffer responseDataSegment = ByteBuffer.allocate(dataSegmentLength);
62          responseDataSegment.put(pdu.getDataSegment().array(),// source array,
63                  0,// offset within the array of the first byte to be read
64                  dataSegmentLength);// length
65  
66          // send response
67          final ProtocolDataUnit responsePdu = TargetPduFactory.createNopInPDU(0,// logicalUnitNumber,
68                                                                                 // reserved
69                  bhs.getInitiatorTaskTag(),// initiatorTaskTag
70                  RESERVED_TAG_VALUE,// targetTransferTag
71                  responseDataSegment, parser.getExpectedStatusSequenceNumber());
72          connection.sendPdu(responsePdu);
73      }
74  
75  }