1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.waarp.ftp.core.data;
19
20 import java.net.InetAddress;
21 import java.net.InetSocketAddress;
22
23 import io.netty.channel.Channel;
24
25 import org.waarp.common.command.exception.Reply425Exception;
26 import org.waarp.common.crypto.ssl.WaarpSslUtility;
27 import org.waarp.common.logging.WaarpLogger;
28 import org.waarp.common.logging.WaarpLoggerFactory;
29 import org.waarp.ftp.core.command.FtpArgumentCode;
30 import org.waarp.ftp.core.command.FtpArgumentCode.TransferMode;
31 import org.waarp.ftp.core.command.FtpArgumentCode.TransferStructure;
32 import org.waarp.ftp.core.command.FtpArgumentCode.TransferType;
33 import org.waarp.ftp.core.config.FtpConfiguration;
34 import org.waarp.ftp.core.data.handler.DataNetworkHandler;
35 import org.waarp.ftp.core.exception.FtpNoConnectionException;
36 import org.waarp.ftp.core.session.FtpSession;
37 import org.waarp.ftp.core.utils.FtpChannelUtils;
38
39
40
41
42
43
44
45 public class FtpDataAsyncConn {
46
47
48
49 private static final WaarpLogger logger = WaarpLoggerFactory.getLogger(FtpDataAsyncConn.class);
50
51
52
53 private final FtpSession session;
54
55
56
57
58 private volatile DataNetworkHandler dataNetworkHandler = null;
59
60
61
62
63 private volatile Channel dataChannel = null;
64
65
66
67
68 private volatile InetSocketAddress remoteAddress = null;
69
70
71
72
73 private volatile InetSocketAddress localAddress = null;
74
75
76
77
78
79 private volatile int remotePort = -1;
80
81
82
83
84
85 private volatile int localPort = -1;
86
87
88
89
90 private volatile boolean passiveMode = false;
91
92
93
94
95 private volatile boolean isBind = false;
96
97
98
99
100 private final FtpTransferControl transferControl;
101
102
103
104
105 private volatile FtpArgumentCode.TransferType transferType = FtpArgumentCode.TransferType.ASCII;
106
107
108
109
110 private volatile FtpArgumentCode.TransferSubType transferSubType = FtpArgumentCode.TransferSubType.NONPRINT;
111
112
113
114
115 private volatile FtpArgumentCode.TransferStructure transferStructure = FtpArgumentCode.TransferStructure.FILE;
116
117
118
119
120 private volatile FtpArgumentCode.TransferMode transferMode = FtpArgumentCode.TransferMode.STREAM;
121
122
123
124
125
126
127 public FtpDataAsyncConn(FtpSession session) {
128 this.session = session;
129 dataChannel = null;
130 remoteAddress = FtpChannelUtils.getRemoteInetSocketAddress(this.session.getControlChannel());
131 remotePort = remoteAddress.getPort();
132 setDefaultLocalPort();
133 resetLocalAddress();
134 passiveMode = false;
135 isBind = false;
136 transferControl = new FtpTransferControl(session);
137 }
138
139
140
141
142
143
144 public boolean checkCorrectChannel(Channel channel) {
145 if (this.dataChannel == null || channel == null) {
146 return false;
147 }
148 return dataChannel.compareTo(channel) == 0;
149 }
150
151
152
153
154
155 public void clear() {
156 unbindPassive();
157 transferControl.clear();
158 passiveMode = false;
159 remotePort = -1;
160 localPort = -1;
161 }
162
163
164
165
166
167 private void setDefaultLocalPort() {
168 setLocalPort(session.getConfiguration().getServerPort() - 1);
169
170 }
171
172
173
174
175
176
177 public void setLocalPort(int localPort) {
178 this.localPort = localPort;
179 }
180
181
182
183
184 public InetSocketAddress getLocalAddress() {
185 return localAddress;
186 }
187
188
189
190
191 public InetSocketAddress getRemoteAddress() {
192 return remoteAddress;
193 }
194
195
196
197
198 public int getRemotePort() {
199 return remotePort;
200 }
201
202
203
204
205 public int getLocalPort() {
206 return localPort;
207 }
208
209 private void resetLocalAddress() {
210 localAddress = new InetSocketAddress(FtpChannelUtils
211 .getLocalInetAddress(session.getControlChannel()), localPort);
212 }
213
214
215
216
217
218
219
220 public void setActive(InetSocketAddress address) {
221 unbindPassive();
222 setDefaultLocalPort();
223 resetLocalAddress();
224 remoteAddress = address;
225 passiveMode = false;
226 isBind = false;
227 remotePort = remoteAddress.getPort();
228 logger.debug("SetActive: " + this);
229 }
230
231
232
233
234
235 public void setPassive() {
236 unbindPassive();
237 resetLocalAddress();
238 passiveMode = true;
239 isBind = false;
240 logger.debug("SetPassive: " + this);
241 }
242
243
244
245
246 public boolean isPassiveMode() {
247 return passiveMode;
248 }
249
250
251
252
253
254
255 public boolean isBind() {
256 return isBind;
257 }
258
259
260
261
262
263
264 public boolean isActive() {
265 return dataChannel != null && dataChannel.isActive();
266 }
267
268
269
270
271 public FtpArgumentCode.TransferMode getMode() {
272 return transferMode;
273 }
274
275
276
277
278
279 public void setMode(FtpArgumentCode.TransferMode transferMode) {
280 this.transferMode = transferMode;
281 setCorrectCodec();
282 }
283
284
285
286
287 public FtpArgumentCode.TransferStructure getStructure() {
288 return transferStructure;
289 }
290
291
292
293
294
295 public void setStructure(FtpArgumentCode.TransferStructure transferStructure) {
296 this.transferStructure = transferStructure;
297 setCorrectCodec();
298 }
299
300
301
302
303 public FtpArgumentCode.TransferSubType getSubType() {
304 return transferSubType;
305 }
306
307
308
309
310
311 public void setSubType(FtpArgumentCode.TransferSubType transferSubType) {
312 this.transferSubType = transferSubType;
313 setCorrectCodec();
314 }
315
316
317
318
319 public FtpArgumentCode.TransferType getType() {
320 return transferType;
321 }
322
323
324
325
326
327 public void setType(FtpArgumentCode.TransferType transferType) {
328 this.transferType = transferType;
329 setCorrectCodec();
330 }
331
332
333
334
335
336
337 public boolean isFileStreamBlockAsciiImage() {
338 return transferStructure == TransferStructure.FILE &&
339 (transferMode == TransferMode.STREAM || transferMode == TransferMode.BLOCK) &&
340 (transferType == TransferType.ASCII || transferType == TransferType.IMAGE);
341 }
342
343
344
345
346
347 public boolean isStreamFile() {
348 return transferMode == TransferMode.STREAM &&
349 transferStructure == TransferStructure.FILE;
350 }
351
352
353
354
355
356 private void setCorrectCodec() {
357 try {
358 getDataNetworkHandler().setCorrectCodec();
359 } catch (FtpNoConnectionException e) {
360 }
361 }
362
363
364
365
366
367 public void unbindPassive() {
368 if (isBind && passiveMode) {
369 isBind = false;
370 InetSocketAddress local = getLocalAddress();
371 if (dataChannel != null && dataChannel.isActive()) {
372 WaarpSslUtility.closingSslChannel(dataChannel);
373 }
374 session.getConfiguration().getFtpInternalConfiguration()
375 .unbindPassive(local);
376
377
378 InetAddress remote = remoteAddress.getAddress();
379 session.getConfiguration().delFtpSession(remote, local);
380 }
381 dataChannel = null;
382 dataNetworkHandler = null;
383 }
384
385
386
387
388
389
390
391 public boolean initPassiveConnection() throws Reply425Exception {
392 unbindPassive();
393 if (passiveMode) {
394
395 session.getConfiguration().getFtpInternalConfiguration()
396 .bindPassive(getLocalAddress(), session.isDataSsl());
397 isBind = true;
398 return true;
399 }
400
401 return true;
402 }
403
404
405
406
407
408
409
410 public Channel getCurrentDataChannel() throws FtpNoConnectionException {
411 if (dataChannel == null) {
412 throw new FtpNoConnectionException("No Data Connection active");
413 }
414 return dataChannel;
415 }
416
417
418
419
420
421
422 public DataNetworkHandler getDataNetworkHandler()
423 throws FtpNoConnectionException {
424 if (dataNetworkHandler == null) {
425 throw new FtpNoConnectionException("No Data Connection active");
426 }
427 return dataNetworkHandler;
428 }
429
430
431
432
433
434
435 public void setDataNetworkHandler(DataNetworkHandler dataNetworkHandler) {
436 this.dataNetworkHandler = dataNetworkHandler;
437 }
438
439
440
441
442
443
444 public static int getNewPassivePort(FtpConfiguration configuration) {
445 return configuration.getNextRangePort();
446 }
447
448
449
450
451 public String getStatus() {
452 StringBuilder builder = new StringBuilder("Data connection: ")
453 .append((isActive() ? "connected " : "not connected "))
454 .append((isBind() ? "bind " : "not bind "))
455 .append((isPassiveMode() ? "passive mode" : "active mode"))
456 .append('\n')
457 .append("Mode: ").append(transferMode.name()).append(" localPort: ")
458 .append(getLocalPort()).append(" remotePort: ").append(getRemotePort()).append('\n')
459 .append("Structure: ").append(transferStructure.name()).append('\n')
460 .append("Type: ").append(transferType.name()).append(' ').append(transferSubType.name());
461 return builder.toString();
462 }
463
464
465
466
467 @Override
468 public String toString() {
469 return getStatus().replace('\n', ' ');
470 }
471
472
473
474
475
476 public FtpTransferControl getFtpTransferControl() {
477 return transferControl;
478 }
479
480
481
482
483
484
485
486
487
488 public void setNewOpenedDataChannel(Channel dataChannel)
489 throws InterruptedException, Reply425Exception {
490 this.dataChannel = dataChannel;
491 if (dataChannel == null) {
492 String curmode = null;
493 if (isPassiveMode()) {
494 curmode = "passive";
495 } else {
496 curmode = "active";
497 }
498
499 throw new Reply425Exception("Cannot open " + curmode +
500 " data connection");
501 }
502 isBind = true;
503 }
504 }