1 package org.jscsi.target.connection;
2
3
4 import java.io.IOException;
5 import java.nio.channels.ClosedChannelException;
6 import java.nio.channels.SocketChannel;
7 import java.security.DigestException;
8
9 import org.jscsi.exception.InternetSCSIException;
10 import org.jscsi.parser.BasicHeaderSegment;
11 import org.jscsi.parser.InitiatorMessageParser;
12 import org.jscsi.parser.OperationCode;
13 import org.jscsi.parser.ProtocolDataUnit;
14 import org.jscsi.parser.ProtocolDataUnitFactory;
15 import org.jscsi.parser.TargetMessageParser;
16 import org.jscsi.parser.scsi.SCSICommandParser;
17 import org.jscsi.target.scsi.cdb.ScsiOperationCode;
18 import org.jscsi.target.settings.Settings;
19 import org.jscsi.target.settings.SettingsException;
20 import org.jscsi.target.settings.TextKeyword;
21 import org.jscsi.target.util.Debug;
22 import org.slf4j.Logger;
23 import org.slf4j.LoggerFactory;
24
25
26
27
28
29
30
31
32 public class TargetSenderWorker {
33
34 private static final Logger LOGGER = LoggerFactory.getLogger(TargetSenderWorker.class);
35
36
37
38
39 final private Connection connection;
40
41
42
43
44 private TargetSession session;
45
46
47
48
49 final private SocketChannel socketChannel;
50
51
52
53
54
55 final private ProtocolDataUnitFactory protocolDataUnitFactory;
56
57
58
59
60
61
62
63
64
65
66
67
68 private boolean initialPdu;
69
70
71
72
73
74
75
76 public TargetSenderWorker (final Connection connection, final SocketChannel socketChannel) {
77 this.connection = connection;
78 this.socketChannel = socketChannel;
79 protocolDataUnitFactory = new ProtocolDataUnitFactory();
80 initialPdu = connection.isLeadingConnection();
81 }
82
83
84
85
86
87
88
89
90
91
92 void setSession (final TargetSession session) {
93 this.session = session;
94 }
95
96
97
98
99
100
101 public final void close () throws IOException {
102 socketChannel.close();
103 }
104
105
106
107
108
109
110
111
112
113
114
115 ProtocolDataUnit receiveFromWire () throws DigestException , InternetSCSIException , IOException , SettingsException {
116
117 ProtocolDataUnit pdu;
118 if (initialPdu) {
119
120
121
122
123 pdu = protocolDataUnitFactory.create(TextKeyword.NONE,
124
125 TextKeyword.NONE);
126 } else {
127
128 final Settings settings = connection.getSettings();
129 pdu = protocolDataUnitFactory.create(settings.getHeaderDigest(), settings.getDataDigest());
130 }
131
132 try {
133 pdu.read(socketChannel);
134 } catch (ClosedChannelException e) {
135 throw new InternetSCSIException(e);
136 }
137
138 if (LOGGER.isDebugEnabled()) LOGGER.debug("Receiving this PDU:\n" + pdu);
139
140
141 final BasicHeaderSegment bhs = pdu.getBasicHeaderSegment();
142 final InitiatorMessageParser parser = (InitiatorMessageParser) bhs.getParser();
143
144
145
146 if (LOGGER.isDebugEnabled()) {
147
148
149 if (bhs.getOpCode() == OperationCode.SCSI_COMMAND) {
150 final SCSICommandParser scsiParser = (SCSICommandParser) bhs.getParser();
151 ScsiOperationCode scsiOpCode = ScsiOperationCode.valueOf(scsiParser.getCDB().get(0));
152 LOGGER.debug("scsiOpCode = " + scsiOpCode);
153 LOGGER.debug("CDB bytes: \n" + Debug.byteBufferToString(scsiParser.getCDB()));
154 }
155
156 if (connection == null)
157 LOGGER.debug("connection: null");
158 else if (connection.getStatusSequenceNumber() == null)
159 LOGGER.debug("connection.getStatusSequenceNumber: null");
160 else
161 LOGGER.debug("connection.getStatusSequenceNumber: " + connection.getStatusSequenceNumber().getValue());
162 }
163
164
165
166 if (initialPdu) {
167 initialPdu = false;
168
169
170
171
172
173 } else {
174
175
176
177
178
179
180
181
182
183
184 }
185
186
187 try {
188 if (parser.incrementSequenceNumber()) session.getExpectedCommandSequenceNumber().increment();
189 } catch (NullPointerException exc) {
190
191 }
192
193 return pdu;
194 }
195
196
197
198
199
200
201
202
203
204
205
206
207 final void sendOverWire (final ProtocolDataUnit pdu) throws InternetSCSIException , IOException , InterruptedException {
208
209
210 final TargetMessageParser parser = (TargetMessageParser) pdu.getBasicHeaderSegment().getParser();
211 parser.setExpectedCommandSequenceNumber(session.getExpectedCommandSequenceNumber().getValue());
212 parser.setMaximumCommandSequenceNumber(session.getMaximumCommandSequenceNumber().getValue());
213 final boolean incrementSequenceNumber = parser.incrementSequenceNumber();
214 if (incrementSequenceNumber)
215 parser.setStatusSequenceNumber(connection.getStatusSequenceNumber().getValue());
216
217 if (LOGGER.isDebugEnabled()) LOGGER.debug("Sending this PDU:\n" + pdu);
218
219
220 pdu.write(socketChannel);
221
222
223
224 if (incrementSequenceNumber) connection.getStatusSequenceNumber().increment();
225
226 }
227 }