1 package org.jscsi.target.connection.stage.login;
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.OperationCode;
11 import org.jscsi.parser.ProtocolDataUnit;
12 import org.jscsi.parser.login.LoginRequestParser;
13 import org.jscsi.parser.login.LoginStage;
14 import org.jscsi.parser.login.LoginStatus;
15 import org.jscsi.target.connection.TargetPduFactory;
16 import org.jscsi.target.connection.phase.TargetLoginPhase;
17 import org.jscsi.target.connection.stage.TargetStage;
18 import org.jscsi.target.settings.ConnectionSettingsNegotiator;
19 import org.jscsi.target.settings.SettingsException;
20 import org.jscsi.target.util.ReadWrite;
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36 public abstract class TargetLoginStage extends TargetStage {
37
38
39
40
41 protected final ConnectionSettingsNegotiator negotiator;
42
43
44
45
46
47
48
49 protected final LoginStage stageNumber;
50
51
52
53
54 protected int initiatorTaskTag;
55
56
57
58
59
60
61
62 protected LoginStage requestedNextStageNumber;
63
64
65
66
67
68
69
70
71
72 protected LoginStage nextStageNumber;
73
74
75
76
77
78
79
80 public TargetLoginStage (final TargetLoginPhase targetLoginPhase, final LoginStage stageNumber) {
81 super(targetLoginPhase);
82 this.stageNumber = stageNumber;
83 negotiator = connection.getConnectionSettingsNegotiator();
84 }
85
86
87
88
89
90
91
92
93 protected boolean checkPdu (ProtocolDataUnit pdu) {
94 final BasicHeaderSegment bhs = pdu.getBasicHeaderSegment();
95 final LoginRequestParser parser = (LoginRequestParser) bhs.getParser();
96 if (bhs.getOpCode() == OperationCode.LOGIN_REQUEST && parser.getCurrentStageNumber() == stageNumber && bhs.getInitiatorTaskTag() == initiatorTaskTag) return true;
97 return false;
98 }
99
100
101
102
103
104
105
106
107
108
109
110
111 protected final String receivePduSequence () throws DigestException , InternetSCSIException , IOException , SettingsException , InterruptedException {
112 final ProtocolDataUnit pdu = connection.receivePdu();
113 return receivePduSequence(pdu);
114 }
115
116
117
118
119
120
121
122
123
124
125
126
127
128 protected final String receivePduSequence (ProtocolDataUnit pdu) throws InternetSCSIException , InterruptedException , IOException , DigestException , SettingsException {
129
130
131 final StringBuilder stringBuilder = new StringBuilder();
132
133
134 BasicHeaderSegment bhs;
135 LoginRequestParser parser;
136
137
138 int sequenceLength = 1;
139 while (sequenceLength <= session.getTargetServer().getConfig().getInMaxRecvTextPduSequenceLength()) {
140 bhs = pdu.getBasicHeaderSegment();
141 parser = (LoginRequestParser) bhs.getParser();
142
143
144 if (!checkPdu(pdu)) {
145
146 sendRejectPdu(LoginStatus.INVALID_DURING_LOGIN);
147 throw new InternetSCSIException("Wrong PDU in TargetLoginStage");
148 }
149
150
151 ReadWrite.appendTextDataSegmentToStringBuffer(pdu.getDataSegment(), stringBuilder);
152
153
154 requestedNextStageNumber = parser.getNextStageNumber();
155
156
157 if (parser.isContinueFlag()) {
158
159 pdu = TargetPduFactory.createLoginResponsePdu(false,
160 false,
161 stageNumber,
162 stageNumber,
163 session.getInitiatorSessionID(),
164 session.getTargetSessionIdentifyingHandle(),
165 initiatorTaskTag, LoginStatus.SUCCESS,
166 ByteBuffer.allocate(0));
167 connection.sendPdu(pdu);
168
169
170 pdu = connection.receivePdu();
171 } else
172
173 return stringBuilder.toString();
174 }
175
176
177
178 sendRejectPdu(LoginStatus.OUT_OF_RESOURCES);
179 throw new InternetSCSIException("Wrong PDU in TargetLoginStage");
180 }
181
182
183
184
185
186
187
188
189
190
191
192
193 protected final void sendPduSequence (final String keyValuePairs, final LoginStage nextStage) throws SettingsException , InterruptedException , IOException , InternetSCSIException , DigestException {
194
195
196 ProtocolDataUnit pdu;
197 BasicHeaderSegment bhs;
198 LoginRequestParser parser;
199 boolean continueFlag = true;
200 boolean transitFlag = false;
201
202
203 final ByteBuffer[] dataSegments = ReadWrite.stringToTextDataSegments(keyValuePairs,
204 settings.getMaxRecvDataSegmentLength());
205
206
207 for (int i = 0; i < dataSegments.length; ++i) {
208
209
210 if (i == dataSegments.length - 1) {
211 continueFlag = false;
212 if (stageNumber != nextStage) transitFlag = true;
213 }
214
215
216 pdu = TargetPduFactory.createLoginResponsePdu(transitFlag,
217 continueFlag,
218 stageNumber,
219 nextStage,
220 session.getInitiatorSessionID(),
221 session.getTargetSessionIdentifyingHandle(),
222 initiatorTaskTag, LoginStatus.SUCCESS,
223 dataSegments[i]);
224 connection.sendPdu(pdu);
225
226
227 if (continueFlag) {
228
229 pdu = connection.receivePdu();
230 bhs = pdu.getBasicHeaderSegment();
231 parser = (LoginRequestParser) bhs.getParser();
232 if (!checkPdu(pdu) || parser.isContinueFlag()) {
233
234 sendRejectPdu(LoginStatus.INITIATOR_ERROR);
235 throw new InternetSCSIException();
236 }
237 }
238 }
239 }
240
241
242
243
244
245
246
247
248
249
250 protected final void sendRejectPdu (final LoginStatus errorStatus) throws InterruptedException , IOException , InternetSCSIException {
251 final ProtocolDataUnit rejectPDU = TargetPduFactory.createLoginResponsePdu(false,
252 false,
253 stageNumber,
254 stageNumber,
255 session.getInitiatorSessionID(),
256 session.getTargetSessionIdentifyingHandle(),
257 initiatorTaskTag,
258 errorStatus,
259 ByteBuffer.allocate(0));
260 connection.sendPdu(rejectPDU);
261 }
262
263
264
265
266
267
268
269 public final LoginStage getNextStageNumber () {
270 return nextStageNumber;
271 }
272 }