1 package org.jscsi.target.connection.stage.fullfeature;
2
3 import java.io.IOException;
4 import java.nio.ByteBuffer;
5
6 import org.jscsi.exception.InternetSCSIException;
7 import org.jscsi.parser.ProtocolDataUnit;
8 import org.jscsi.parser.scsi.SCSIResponseParser;
9 import org.jscsi.parser.scsi.SCSIStatus;
10 import org.jscsi.target.connection.TargetPduFactory;
11 import org.jscsi.target.connection.phase.TargetFullFeaturePhase;
12 import org.jscsi.target.connection.stage.TargetStage;
13 import org.jscsi.target.scsi.IResponseData;
14 import org.jscsi.target.scsi.ScsiResponseDataSegment;
15 import org.jscsi.target.scsi.sense.AdditionalSenseBytes;
16 import org.jscsi.target.scsi.sense.AdditionalSenseCodeAndQualifier;
17 import org.jscsi.target.scsi.sense.ErrorType;
18 import org.jscsi.target.scsi.sense.FixedFormatSenseData;
19 import org.jscsi.target.scsi.sense.SenseKey;
20 import org.jscsi.target.scsi.sense.information.FourByteInformation;
21 import org.jscsi.target.scsi.sense.senseDataDescriptor.senseKeySpecific.FieldPointerSenseKeySpecificData;
22
23
24
25
26
27
28
29 public abstract class TargetFullFeatureStage extends TargetStage {
30
31
32
33
34
35
36
37 public TargetFullFeatureStage(TargetFullFeaturePhase targetFullFeaturePhase) {
38 super(targetFullFeaturePhase);
39 }
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57 protected static final ProtocolDataUnit createFixedFormatErrorPdu(
58 final FieldPointerSenseKeySpecificData[] senseKeySpecificData,
59 final AdditionalSenseCodeAndQualifier additionalSenseCodeAndQualifier, final int initiatorTaskTag,
60 final int expectedDataTransferLength) {
61
62
63 FixedFormatSenseData senseData = new FixedFormatSenseData(false,
64 ErrorType.CURRENT,
65 false,
66 false,
67 false,
68 SenseKey.ILLEGAL_REQUEST,
69 new FourByteInformation(),
70 new FourByteInformation(),
71 additionalSenseCodeAndQualifier,
72
73 (byte)0,
74 senseKeySpecificData[0],
75
76 new AdditionalSenseBytes());
77
78
79 final ScsiResponseDataSegment dataSegment =
80 new ScsiResponseDataSegment(senseData, expectedDataTransferLength);
81 final int senseDataSize = senseData.size();
82
83
84 final int residualCount = Math.abs(expectedDataTransferLength - senseDataSize);
85 final boolean residualOverflow = expectedDataTransferLength < senseDataSize;
86 final boolean residualUnderflow = expectedDataTransferLength > senseDataSize;
87
88
89 return TargetPduFactory.createSCSIResponsePdu(false,
90 false,
91 residualOverflow,
92 residualUnderflow,
93 SCSIResponseParser.ServiceResponse.COMMAND_COMPLETED_AT_TARGET,
94 SCSIStatus.CHECK_CONDITION,
95 initiatorTaskTag,
96 0,
97 0,
98 0,
99 residualCount,
100 dataSegment);
101 }
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118 protected static final ProtocolDataUnit createFixedFormatErrorPdu(
119 final FieldPointerSenseKeySpecificData[] senseKeySpecificData, final int initiatorTaskTag,
120 final int expectedDataTransferLength) {
121 return createFixedFormatErrorPdu(senseKeySpecificData,
122 AdditionalSenseCodeAndQualifier.INVALID_FIELD_IN_CDB, initiatorTaskTag,
123 expectedDataTransferLength);
124 }
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145 protected static final ProtocolDataUnit createScsiResponsePdu(final SCSIStatus status,
146 final int initiatorTaskTag, final int expectedDataTransferLength, final int responseDataSize) {
147
148
149 final int residualCount = Math.abs(expectedDataTransferLength - responseDataSize);
150 final boolean residualOverflow = expectedDataTransferLength < responseDataSize;
151 final boolean residualUnderflow = expectedDataTransferLength > responseDataSize;
152
153 return TargetPduFactory.createSCSIResponsePdu(false,
154 false,
155 residualOverflow,
156 residualUnderflow,
157 SCSIResponseParser.ServiceResponse.COMMAND_COMPLETED_AT_TARGET,
158 status,
159 initiatorTaskTag,
160 0,
161 0,
162 0,
163 residualCount,
164 ScsiResponseDataSegment.EMPTY_DATA_SEGMENT);
165 }
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184 protected final void sendResponse(final int initiatorTaskTag, final int expectedDataTransferLength,
185 final IResponseData responseData) throws InterruptedException, IOException, InternetSCSIException {
186
187
188 final ByteBuffer fullBuffer = ByteBuffer.allocate(responseData.size());
189 responseData.serialize(fullBuffer, 0);
190
191
192
193 ByteBuffer trimmedBuffer;
194 if (fullBuffer.capacity() <= expectedDataTransferLength) {
195
196 trimmedBuffer = fullBuffer;
197 } else {
198 trimmedBuffer = ByteBuffer.allocate(expectedDataTransferLength);
199 trimmedBuffer.put(fullBuffer.array(),
200 0,
201 expectedDataTransferLength);
202 }
203
204
205 final boolean residualOverflow = expectedDataTransferLength < fullBuffer.capacity();
206 final boolean residualUnderflow = expectedDataTransferLength > fullBuffer.capacity();
207 final int residualCount = Math.abs(expectedDataTransferLength - fullBuffer.capacity());
208
209
210 ProtocolDataUnit pdu = TargetPduFactory.createDataInPdu(true,
211 false,
212 residualOverflow,
213 residualUnderflow,
214 true,
215 SCSIStatus.GOOD,
216 0,
217 initiatorTaskTag,
218 -1,
219 0,
220 0,
221 residualCount,
222 trimmedBuffer);
223
224 connection.sendPdu(pdu);
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243 }
244 }