View Javadoc

1   package org.jscsi.target.connection.stage.fullfeature;
2   
3   
4   import java.io.IOException;
5   import java.security.DigestException;
6   
7   import org.jscsi.exception.InternetSCSIException;
8   import org.jscsi.parser.BasicHeaderSegment;
9   import org.jscsi.parser.ProtocolDataUnit;
10  import org.jscsi.parser.scsi.SCSICommandParser;
11  import org.jscsi.parser.scsi.SCSIResponseParser;
12  import org.jscsi.parser.scsi.SCSIStatus;
13  import org.jscsi.target.connection.TargetPduFactory;
14  import org.jscsi.target.connection.phase.TargetFullFeaturePhase;
15  import org.jscsi.target.scsi.ScsiResponseDataSegment;
16  import org.jscsi.target.scsi.cdb.RequestSenseCdb;
17  import org.jscsi.target.scsi.sense.AdditionalSenseBytes;
18  import org.jscsi.target.scsi.sense.AdditionalSenseCodeAndQualifier;
19  import org.jscsi.target.scsi.sense.DescriptorFormatSenseData;
20  import org.jscsi.target.scsi.sense.ErrorType;
21  import org.jscsi.target.scsi.sense.FixedFormatSenseData;
22  import org.jscsi.target.scsi.sense.SenseData;
23  import org.jscsi.target.scsi.sense.SenseKey;
24  import org.jscsi.target.scsi.sense.information.FourByteInformation;
25  import org.jscsi.target.scsi.sense.senseDataDescriptor.SenseDataDescriptor;
26  import org.jscsi.target.scsi.sense.senseDataDescriptor.senseKeySpecific.FieldPointerSenseKeySpecificData;
27  import org.jscsi.target.settings.SettingsException;
28  
29  
30  /**
31   * A stage for processing <code>REQUEST SENSE</code> SCSI commands.
32   * <p>
33   * The <code>REQUEST SENSE</code> command requests that the device server transfer {@link SenseData} to the application
34   * client.
35   * 
36   * @author Andreas Ergenzinger
37   */
38  public class RequestSenseStage extends TargetFullFeatureStage {
39  
40      public RequestSenseStage (TargetFullFeaturePhase targetFullFeaturePhase) {
41          super(targetFullFeaturePhase);
42      }
43  
44      @Override
45      public void execute (ProtocolDataUnit pdu) throws IOException , InterruptedException , InternetSCSIException , DigestException , SettingsException {
46  
47          final BasicHeaderSegment bhs = pdu.getBasicHeaderSegment();
48          final SCSICommandParser parser = (SCSICommandParser) bhs.getParser();
49  
50          ProtocolDataUnit responsePDU = null;// the response PDU
51  
52          // get command details in CDB
53          final RequestSenseCdb cdb = new RequestSenseCdb(parser.getCDB());
54          final FieldPointerSenseKeySpecificData[] illegalFieldPointers = cdb.getIllegalFieldPointers();
55  
56          if (illegalFieldPointers != null) {
57              // an illegal request has been made
58  
59              SenseData senseData;
60  
61              if (cdb.getDescriptorFormat()) {
62                  // descriptor format sense data has been requested
63  
64                  senseData = new DescriptorFormatSenseData(ErrorType.CURRENT,// errorType
65                  SenseKey.ILLEGAL_REQUEST,// sense key
66                  AdditionalSenseCodeAndQualifier.INVALID_FIELD_IN_CDB,// additional
67                                                                       // sense
68                                                                       // code
69                                                                       // and
70                                                                       // qualifier
71                  new SenseDataDescriptor[0]);// sense data descriptors
72  
73              } else {
74                  // fixed format sense data has been requested
75  
76                  senseData = new FixedFormatSenseData(false,// valid
77                  ErrorType.CURRENT,// error type
78                  false,// file mark
79                  false,// end of medium
80                  false,// incorrect length indicator
81                  SenseKey.ILLEGAL_REQUEST,// sense key
82                  new FourByteInformation(),// information
83                  new FourByteInformation(),// command specific
84                                            // information
85                  AdditionalSenseCodeAndQualifier.INVALID_FIELD_IN_CDB,// additional
86                                                                       // sense
87                                                                       // code
88                                                                       // and
89                                                                       // qualifier
90                  (byte) 0,// field replaceable unit code
91                  illegalFieldPointers[0],// sense key specific data, only
92                                          // report first problem
93                  new AdditionalSenseBytes());// additional sense bytes
94              }
95  
96              responsePDU = TargetPduFactory.createSCSIResponsePdu(false,// bidirectionalReadResidualOverflow
97                      false,// bidirectionalReadResidualUnderflow
98                      false,// residualOverflow
99                      false,// residualUnderflow,
100                     SCSIResponseParser.ServiceResponse.TARGET_FAILURE,// response,
101                     SCSIStatus.CHECK_CONDITION,// status,
102                     bhs.getInitiatorTaskTag(),// initiatorTaskTag,
103                     0,// snackTag
104                     0,// expectedDataSequenceNumber
105                     0,// bidirectionalReadResidualCount
106                     0,// residualCount
107                     new ScsiResponseDataSegment(senseData, parser.getExpectedDataTransferLength()));// data
108                                                                                                     // segment
109 
110         } else {
111             /*
112              * PDU is okay carry out command Sense data shall be available and cleared under the conditions defined in
113              * SAM-3. If the device server has no other sense data available to return, it shall return the sense key
114              * set to NO SENSE and the additional sense code set to NO ADDITIONAL SENSE INFORMATION. This will always be
115              * the case with the jSCSI Target.
116              */
117 
118             SenseData senseData;
119 
120             final SenseKey senseKey = SenseKey.NO_SENSE;
121             final AdditionalSenseCodeAndQualifier additionalSense = AdditionalSenseCodeAndQualifier.NO_ADDITIONAL_SENSE_INFORMATION;
122 
123             if (cdb.getDescriptorFormat()) {
124                 // descriptor format sense data has been requested
125 
126                 senseData = new DescriptorFormatSenseData(ErrorType.CURRENT,// errorType
127                 senseKey,// sense key
128                 additionalSense,// additional sense code and qualifier
129                 new SenseDataDescriptor[0]);// sense data descriptors
130 
131             } else {
132                 // fixed format sense data has been requested
133 
134                 senseData = new FixedFormatSenseData(false,// valid
135                 ErrorType.CURRENT,// error type
136                 false,// file mark
137                 false,// end of medium
138                 false,// incorrect length indicator
139                 senseKey,// sense key
140                 new FourByteInformation(),// information
141                 new FourByteInformation(),// command specific
142                                           // information
143                 additionalSense,// additional sense code and qualifier
144                 (byte) 0,// field replaceable unit code
145                 null,// sense key specific data, only report first
146                      // problem
147                 null);// additional sense bytes
148             }
149 
150             responsePDU = TargetPduFactory.createSCSIResponsePdu(false,// bidirectionalReadResidualOverflow
151                     false,// bidirectionalReadResidualUnderflow
152                     false,// residualOverflow
153                     false,// residualUnderflow,
154                     SCSIResponseParser.ServiceResponse.COMMAND_COMPLETED_AT_TARGET,// response,
155                     SCSIStatus.GOOD,// status,
156                     bhs.getInitiatorTaskTag(),// initiatorTaskTag,
157                     0,// snackTag
158                     0,// expectedDataSequenceNumber
159                     0,// bidirectionalReadResidualCount
160                     0,// residualCount
161                     new ScsiResponseDataSegment(senseData, parser.getExpectedDataTransferLength()));// data
162                                                                                                     // segment
163         }
164 
165         // send response
166         connection.sendPdu(responsePDU);
167     }
168 
169 }