View Javadoc

1   package org.jscsi.target.connection.phase;
2   
3   
4   import java.io.IOException;
5   import java.security.DigestException;
6   
7   import javax.naming.OperationNotSupportedException;
8   
9   import org.jscsi.exception.InternetSCSIException;
10  import org.jscsi.parser.BasicHeaderSegment;
11  import org.jscsi.parser.ProtocolDataUnit;
12  import org.jscsi.parser.scsi.SCSICommandParser;
13  import org.jscsi.target.connection.Connection;
14  import org.jscsi.target.connection.stage.TMStage;
15  import org.jscsi.target.connection.stage.fullfeature.FormatUnitStage;
16  import org.jscsi.target.connection.stage.fullfeature.InquiryStage;
17  import org.jscsi.target.connection.stage.fullfeature.LogoutStage;
18  import org.jscsi.target.connection.stage.fullfeature.ModeSenseStage;
19  import org.jscsi.target.connection.stage.fullfeature.PingStage;
20  import org.jscsi.target.connection.stage.fullfeature.ReadCapacityStage;
21  import org.jscsi.target.connection.stage.fullfeature.ReadStage;
22  import org.jscsi.target.connection.stage.fullfeature.ReportLunsStage;
23  import org.jscsi.target.connection.stage.fullfeature.RequestSenseStage;
24  import org.jscsi.target.connection.stage.fullfeature.SendDiagnosticStage;
25  import org.jscsi.target.connection.stage.fullfeature.TargetFullFeatureStage;
26  import org.jscsi.target.connection.stage.fullfeature.TestUnitReadyStage;
27  import org.jscsi.target.connection.stage.fullfeature.TextNegotiationStage;
28  import org.jscsi.target.connection.stage.fullfeature.UnsupportedOpCodeStage;
29  import org.jscsi.target.connection.stage.fullfeature.WriteStage;
30  import org.jscsi.target.scsi.cdb.ScsiOperationCode;
31  import org.jscsi.target.settings.SettingsException;
32  import org.slf4j.Logger;
33  import org.slf4j.LoggerFactory;
34  
35  
36  /**
37   * Objects of this class represent the Target Full Feature Phase of a connection.
38   * 
39   * @see TargetPhase
40   * @author Andreas Ergenzinger
41   */
42  public final class TargetFullFeaturePhase extends TargetPhase {
43  
44      private static final Logger LOGGER = LoggerFactory.getLogger(TargetFullFeaturePhase.class);
45  
46      /**
47       * The current stage of this phase.
48       */
49      private TargetFullFeatureStage stage;
50  
51      /**
52       * While this variable is <code>true</code> the phase is still running, either executing a specific stage or waiting
53       * for the next one to begin.
54       */
55      private boolean running;
56  
57      /**
58       * The constructor.
59       * 
60       * @param connection {@inheritDoc}
61       */
62      public TargetFullFeaturePhase (Connection connection) {
63          super(connection);
64  
65      }
66  
67      /**
68       * Starts the full feature phase.
69       * 
70       * @return {@inheritDoc}
71       * @throws OperationNotSupportedException {@inheritDoc}
72       * @throws IOException {@inheritDoc}
73       * @throws InterruptedException {@inheritDoc}
74       * @throws InternetSCSIException {@inheritDoc}
75       * @throws DigestException {@inheritDoc}
76       * @throws SettingsException {@inheritDoc}
77       */
78      public boolean execute () throws DigestException , IOException , InterruptedException , InternetSCSIException , SettingsException {
79  
80          running = true;
81          while (running) {
82              ProtocolDataUnit pdu = connection.receivePdu();
83              BasicHeaderSegment bhs = pdu.getBasicHeaderSegment();
84  
85              // identify desired stage
86              switch (bhs.getOpCode()) {
87  
88                  case SCSI_COMMAND :
89                      if (connection.getTargetSession().isNormalSession()) {
90                          final SCSICommandParser parser = (SCSICommandParser) bhs.getParser();
91                          ScsiOperationCode scsiOpCode = ScsiOperationCode.valueOf(parser.getCDB().get(0));
92  
93                          LOGGER.debug("scsiOpCode = " + scsiOpCode);// log SCSI
94                                                                     // Operation Code
95  
96                          if (scsiOpCode != null) {
97                              switch (scsiOpCode) {
98                                  case TEST_UNIT_READY :
99                                      stage = new TestUnitReadyStage(this);
100                                     break;
101                                 case REQUEST_SENSE :
102                                     stage = new RequestSenseStage(this);
103                                     break;
104                                 case FORMAT_UNIT :
105                                     stage = new FormatUnitStage(this);
106                                     break;
107                                 case INQUIRY :
108                                     stage = new InquiryStage(this);
109                                     break;
110                                 case MODE_SELECT_6 :
111                                     stage = null;
112                                     scsiOpCode = null;
113                                     break;
114                                 case MODE_SENSE_6 :
115                                     stage = new ModeSenseStage(this);
116                                     if (!((ModeSenseStage) stage).canHandle(pdu)) {
117                                         stage = null;
118                                         scsiOpCode = null;
119                                     }
120                                     break;
121                                 case SEND_DIAGNOSTIC :
122                                     stage = new SendDiagnosticStage(this);
123                                     break;
124                                 case READ_CAPACITY_10 :// use common read capacity stage
125                                 case READ_CAPACITY_16 :
126                                     stage = new ReadCapacityStage(this);
127                                     break;
128                                 case WRITE_6 :// use common write stage
129                                 case WRITE_10 :
130                                     stage = new WriteStage(this);
131                                     break;
132                                 case READ_6 :// use common read stage
133                                 case READ_10 :
134                                     stage = new ReadStage(this);
135                                     break;
136                                 case REPORT_LUNS :
137                                     stage = new ReportLunsStage(this);
138                                     break;
139                                 default :
140                                     scsiOpCode = null;
141 
142                             }
143                         }// else, or if default block was entered (programmer error)
144                         if (scsiOpCode == null) {
145                             LOGGER.error("Unsupported SCSI OpCode 0x" + Integer.toHexString(parser.getCDB().get(0) & 255) + " in SCSI Command PDU.");
146                             stage = new UnsupportedOpCodeStage(this);
147                         }
148 
149                     } else {// session is discovery session
150                         throw new InternetSCSIException("received SCSI command in discovery session");
151                     }
152                     break; // SCSI_COMMAND
153 
154                 case SCSI_TM_REQUEST :
155                     stage = new TMStage(this);
156                     break;
157                 case NOP_OUT :
158                     stage = new PingStage(this);
159                     break;
160                 case TEXT_REQUEST :
161                     stage = new TextNegotiationStage(this);
162                     break;
163                 case LOGOUT_REQUEST :
164                     stage = new LogoutStage(this);
165                     running = false;
166                     break;
167                 default :
168                     LOGGER.error("Recieved unsupported opcode for " + pdu.getBasicHeaderSegment().getOpCode());
169                     stage = new UnsupportedOpCodeStage(this);
170             }
171 
172             // process the PDU
173             stage.execute(pdu);
174         }
175 
176         return false;
177     }
178     
179     /**
180      * Stopping this phases execution
181      */
182     public void stop(){
183         this.running = false;
184     }
185 }