@Override
  public void execute(ProtocolDataUnit pdu)
      throws IOException, InterruptedException, InternetSCSIException, DigestException,
          IllegalArgumentException, SettingsException {

    LOGGER.debug("Entering LOPN Stage");

    BasicHeaderSegment bhs = pdu.getBasicHeaderSegment();
    initiatorTaskTag = bhs.getInitiatorTaskTag();

    String keyValuePairProposal = receivePduSequence(pdu);

    // negotiate parameters, leave if unsuccessful
    final Vector<String> requestKeyValuePairs =
        TextParameter.tokenizeKeyValuePairs(keyValuePairProposal);
    final Vector<String> responseKeyValuePairs = new Vector<String>();
    if (!negotiator.negotiate(
        stageNumber,
        connection.isLeadingConnection(),
        ((TargetLoginPhase) targetPhase).getFirstPduAndSetToFalse(),
        requestKeyValuePairs,
        responseKeyValuePairs)) {
      // negotiation failure, no exception
      sendRejectPdu(LoginStatus.INITIATOR_ERROR);
      // nextStageNumber = null;//no change
      return;
    }

    // print request and response key value pairs if debugging
    if (LOGGER.isDebugEnabled()) {
      final StringBuilder sb = new StringBuilder();
      sb.append("request: ");
      for (String s : requestKeyValuePairs) {
        sb.append("\n  ");
        sb.append(s);
      }
      sb.append("\nresponse: ");
      for (String s : responseKeyValuePairs) {
        sb.append("\n  ");
        sb.append(s);
      }
      LOGGER.debug(sb.toString());
    }

    // make sure that initiator wants to proceed to FFP, leave if it does
    // not
    if (requestedNextStageNumber != LoginStage.FULL_FEATURE_PHASE) {
      sendRejectPdu(LoginStatus.INITIATOR_ERROR);
      throw new InternetSCSIException();
    }

    // concatenate key-value pairs to null char-separated string
    final String keyValuePairReply = TextParameter.concatenateKeyValuePairs(responseKeyValuePairs);

    // send reply, finish negotiation, and return successfully
    sendPduSequence(keyValuePairReply, LoginStage.FULL_FEATURE_PHASE);
    negotiator.finishNegotiation(true);
    nextStageNumber = LoginStage.FULL_FEATURE_PHASE;
  }
Exemplo n.º 2
0
  @Override
  public void execute(ProtocolDataUnit pdu)
      throws IOException, InterruptedException, InternetSCSIException, DigestException,
          SettingsException {

    LOGGER.debug("Initiator has sent FORMAT UNIT command.");

    final BasicHeaderSegment bhs = pdu.getBasicHeaderSegment();
    final SCSICommandParser parser = (SCSICommandParser) bhs.getParser();

    ProtocolDataUnit responsePdu = null; // the response PDU

    // get command details in CDB
    final FormatUnitCDB cdb = new FormatUnitCDB(parser.getCDB());
    final FieldPointerSenseKeySpecificData[] illegalFieldPointers = cdb.getIllegalFieldPointers();

    if (illegalFieldPointers != null) {
      // an illegal request has been made

      FixedFormatSenseData senseData =
          new FixedFormatSenseData(
              false, // valid
              ErrorType.CURRENT, // error type
              false, // file mark
              false, // end of medium
              false, // incorrect length indicator
              SenseKey.ILLEGAL_REQUEST, // sense key
              new FourByteInformation(), // information
              new FourByteInformation(), // command specific information
              AdditionalSenseCodeAndQualifier.INVALID_FIELD_IN_CDB, // additional
              // sense
              // code
              // and
              // qualifier
              (byte) 0, // field replaceable unit code
              illegalFieldPointers[0], // sense key specific data, only
              // report first problem
              new AdditionalSenseBytes()); // additional sense bytes

      responsePdu =
          TargetPduFactory.createSCSIResponsePdu(
              false, // bidirectionalReadResidualOverflow
              false, // bidirectionalReadResidualUnderflow
              false, // residualOverflow
              false, // residualUnderflow,
              SCSIResponseParser.ServiceResponse.COMMAND_COMPLETED_AT_TARGET, // response,
              SCSIStatus.CHECK_CONDITION, // status,
              bhs.getInitiatorTaskTag(), // initiatorTaskTag,
              0, // snackTag
              0, // expectedDataSequenceNumber
              0, // bidirectionalReadResidualCount
              0, // residualCount
              new ScsiResponseDataSegment(
                  senseData, parser.getExpectedDataTransferLength())); // data
      // segment

    } else {
      // PDU is okay

      // carry out command
      /*
       * If we were nice, we would have to get (we would actually have to save it first) the number of blocks and
       * the block length requested by the initiator in the last MODE SENSE command and then change the logical
       * block layout accordingly. However, since the target is not required by the SCSI standard to make those
       * changes ("The degree that the medium is altered by this command is vendor specific."), doing nothing is
       * okay.
       */

      responsePdu =
          createScsiResponsePdu(
              SCSIStatus.GOOD, // status
              bhs.getInitiatorTaskTag(), // initiatorTaskTag,
              parser.getExpectedDataTransferLength(), // expectedDataTransferLength,
              0); // responseDataSize
    }

    // send response
    connection.sendPdu(responsePdu);
  }