1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.waarp.ftp.core.session;
19
20 import java.io.File;
21 import java.net.InetAddress;
22 import java.net.InetSocketAddress;
23
24 import io.netty.channel.Channel;
25
26 import org.waarp.common.command.CommandInterface;
27 import org.waarp.common.command.ReplyCode;
28 import org.waarp.common.command.exception.CommandAbstractException;
29 import org.waarp.common.command.exception.Reply425Exception;
30 import org.waarp.common.file.FileParameterInterface;
31 import org.waarp.common.file.Restart;
32 import org.waarp.common.file.SessionInterface;
33 import org.waarp.common.future.WaarpFuture;
34 import org.waarp.common.logging.WaarpLogger;
35 import org.waarp.common.logging.WaarpLoggerFactory;
36 import org.waarp.ftp.core.command.AbstractCommand;
37 import org.waarp.ftp.core.command.FtpArgumentCode;
38 import org.waarp.ftp.core.command.FtpArgumentCode.TransferSubType;
39 import org.waarp.ftp.core.command.internal.ConnectionCommand;
40 import org.waarp.ftp.core.config.FtpConfiguration;
41 import org.waarp.ftp.core.control.BusinessHandler;
42 import org.waarp.ftp.core.control.NetworkHandler;
43 import org.waarp.ftp.core.data.FtpDataAsyncConn;
44 import org.waarp.ftp.core.exception.FtpNoConnectionException;
45 import org.waarp.ftp.core.file.FtpAuth;
46 import org.waarp.ftp.core.file.FtpDir;
47
48
49
50
51
52
53
54
55 public class FtpSession implements SessionInterface {
56
57
58
59 private static final WaarpLogger logger = WaarpLoggerFactory.getLogger(FtpSession.class);
60
61
62
63 private final BusinessHandler businessHandler;
64
65
66
67
68 private final FtpConfiguration configuration;
69
70
71
72
73 private volatile FtpDataAsyncConn dataConn = null;
74
75
76
77
78 private FtpAuth ftpAuth = null;
79
80
81
82
83 private FtpDir ftpDir = null;
84
85
86
87
88 private AbstractCommand previousCommand = null;
89
90
91
92
93 private AbstractCommand currentCommand = null;
94
95
96
97 private volatile boolean isCurrentCommandFinished = true;
98
99
100
101
102 private ReplyCode replyCode = null;
103
104
105
106
107 private String answer = null;
108
109
110
111
112 private Restart restart = null;
113
114
115
116
117 private final WaarpFuture isReady = new WaarpFuture(true);
118
119
120
121
122 private volatile boolean isSsl = false;
123
124
125
126 private volatile WaarpFuture waitForSsl = null;
127
128
129
130 private volatile boolean isDataSsl = false;
131
132
133
134
135
136
137
138 public FtpSession(FtpConfiguration configuration, BusinessHandler handler) {
139 this.configuration = configuration;
140 businessHandler = handler;
141 }
142
143
144
145
146 public BusinessHandler getBusinessHandler() {
147 return businessHandler;
148 }
149
150
151
152
153
154
155 public FtpConfiguration getConfiguration() {
156 return configuration;
157 }
158
159 public FtpDir getDir() {
160 return ftpDir;
161 }
162
163
164
165
166 public FtpDataAsyncConn getDataConn() {
167 return dataConn;
168 }
169
170 public FtpAuth getAuth() {
171 return ftpAuth;
172 }
173
174 public Restart getRestart() {
175 return restart;
176 }
177
178
179
180
181
182 public void setControlConnected() {
183 dataConn = new FtpDataAsyncConn(this);
184
185 ftpAuth = businessHandler.getBusinessNewAuth();
186 ftpDir = businessHandler.getBusinessNewDir();
187 restart = businessHandler.getBusinessNewRestart();
188 }
189
190
191
192
193
194
195
196
197 public void setSpecialInit(FtpAuth auth, FtpDir dir, Restart restart) {
198 this.ftpAuth = auth;
199 this.ftpDir = dir;
200 this.restart = restart;
201 }
202
203
204
205
206 public Channel getControlChannel() {
207 return getNetworkHandler().getControlChannel();
208 }
209
210
211
212
213
214 public NetworkHandler getNetworkHandler() {
215 if (businessHandler != null) {
216 return businessHandler.getNetworkHandler();
217 }
218 return null;
219 }
220
221
222
223
224
225
226 public void setNextCommand(CommandInterface command) {
227 previousCommand = currentCommand;
228 currentCommand = (AbstractCommand) command;
229 isCurrentCommandFinished = false;
230 }
231
232
233
234
235 public AbstractCommand getCurrentCommand() {
236 return currentCommand;
237 }
238
239
240
241
242 public AbstractCommand getPreviousCommand() {
243 return previousCommand;
244 }
245
246
247
248
249
250
251 public void setPreviousAsCurrentCommand() {
252 currentCommand = previousCommand;
253 isCurrentCommandFinished = true;
254 }
255
256
257
258
259
260 public boolean isCurrentCommandFinished() {
261 return isCurrentCommandFinished;
262 }
263
264
265
266
267 public void setCurrentCommandFinished() {
268 this.isCurrentCommandFinished = true;
269 }
270
271
272
273
274 public String getAnswer() {
275 if (answer == null) {
276 if (replyCode == null) {
277 answer = ReplyCode.REPLY_000_SPECIAL_NOSTATUS.getMesg();
278 } else {
279 answer = replyCode.getMesg();
280 }
281 }
282 return answer;
283 }
284
285
286
287
288
289
290 public void setReplyCode(ReplyCode replyCode, String answer) {
291 this.replyCode = replyCode;
292 if (answer != null) {
293 this.answer = ReplyCode.getFinalMsg(replyCode.getCode(), answer);
294 } else {
295 this.answer = replyCode.getMesg();
296 }
297 }
298
299
300
301
302 public void setReplyCode(CommandAbstractException exception) {
303 this.setReplyCode(exception.code, exception.message);
304 }
305
306
307
308
309
310
311 public void setExitErrorCode(String answer) {
312 this.setReplyCode(ReplyCode.REPLY_421_SERVICE_NOT_AVAILABLE_CLOSING_CONTROL_CONNECTION,
313 answer);
314 }
315
316
317
318
319
320
321 public void setExitNormalCode(String answer) {
322 this.setReplyCode(ReplyCode.REPLY_221_CLOSING_CONTROL_CONNECTION,
323 answer);
324 }
325
326
327
328
329 public ReplyCode getReplyCode() {
330 return replyCode;
331 }
332
333 public void clear() {
334 if (dataConn != null) {
335 dataConn.clear();
336 }
337 if (ftpDir != null) {
338 ftpDir.clear();
339 }
340 if (ftpAuth != null) {
341 ftpAuth.clear();
342 }
343 previousCommand = null;
344 replyCode = null;
345 answer = null;
346 isReady.cancel();
347 }
348
349
350
351
352 public boolean isReady() {
353 return isReady.awaitUninterruptibly().isSuccess();
354 }
355
356
357
358
359
360 public void setReady(boolean isReady) {
361 if (isReady) {
362 this.isReady.setSuccess();
363 } else {
364 this.isReady.cancel();
365 }
366 }
367
368 @Override
369 public String toString() {
370 String mesg = "FtpSession: ";
371 if (ftpAuth != null) {
372 mesg += "User: " + ftpAuth.getUser() + "/" + ftpAuth.getAccount() + " ";
373 }
374 if (previousCommand != null) {
375 mesg += "PRVCMD: " + previousCommand.getCommand() + " " +
376 previousCommand.getArg() + " ";
377 }
378 if (currentCommand != null) {
379 mesg += "CMD: " + currentCommand.getCommand() + " " +
380 currentCommand.getArg() + " ";
381 }
382 if (replyCode != null) {
383 mesg += "Reply: " + (answer != null ? answer : replyCode.getMesg()) +
384 " ";
385 }
386 if (dataConn != null) {
387 mesg += dataConn.toString();
388 }
389 if (ftpDir != null) {
390 try {
391 mesg += " PWD: " + ftpDir.getPwd();
392 } catch (CommandAbstractException e) {
393 }
394 }
395 if (getControlChannel() != null) {
396 mesg += " Control: " + getControlChannel();
397 }
398 try {
399 if (getDataConn().getCurrentDataChannel() != null) {
400 mesg += " Data: " + getDataConn().getCurrentDataChannel();
401 }
402 } catch (FtpNoConnectionException e) {
403 }
404 return mesg + "\n";
405 }
406
407 public int getBlockSize() {
408 return restart.getMaxSize(configuration.getBLOCKSIZE());
409 }
410
411 public FileParameterInterface getFileParameter() {
412 return configuration.getFileParameter();
413 }
414
415
416
417
418
419
420 public static String getBasename(String path) {
421 File file = new File(path);
422 return file.getName();
423 }
424
425
426
427
428
429 public void reinitFtpAuth() {
430 AbstractCommand connectioncommand = new ConnectionCommand(this);
431 setNextCommand(connectioncommand);
432 getAuth().clear();
433 getDataConn().clear();
434 getDataConn().getFtpTransferControl().resetWaitForOpenedDataChannel();
435 }
436
437
438
439
440 public void rein() {
441
442 if (getDataConn().isPassiveMode()) {
443
444 InetSocketAddress local = getDataConn().getLocalAddress();
445 InetAddress remote = getDataConn().getRemoteAddress().getAddress();
446 getConfiguration().delFtpSession(remote, local);
447 }
448 getDataConn().setMode(FtpArgumentCode.TransferMode.STREAM);
449 getDataConn().setStructure(FtpArgumentCode.TransferStructure.FILE);
450 getDataConn().setType(FtpArgumentCode.TransferType.ASCII);
451 getDataConn().setSubType(TransferSubType.NONPRINT);
452 reinitFtpAuth();
453 }
454
455
456
457
458
459
460
461 public void openDataConnection() throws Reply425Exception {
462 getDataConn().getFtpTransferControl().openDataConnection();
463 getNetworkHandler().writeIntermediateAnswer();
464 }
465
466 @Override
467 public String getUniqueExtension() {
468 return configuration.getUniqueExtension();
469 }
470
471 public boolean isSsl() {
472 return isSsl;
473 }
474
475 public void setSsl(boolean isSsl) {
476 this.isSsl = isSsl;
477 if (waitForSsl != null) {
478 if (isSsl) {
479 waitForSsl.setSuccess();
480 } else {
481 waitForSsl.cancel();
482 }
483 }
484 }
485
486 public void prepareSsl() {
487 waitForSsl = new WaarpFuture(true);
488 }
489
490 public boolean isSslReady() {
491 if (waitForSsl != null) {
492 for (int i = 0; i < 10; i++) {
493 if (waitForSsl.awaitUninterruptibly(100)) {
494 break;
495 }
496 Thread.yield();
497 }
498 logger.debug("DEBUG : " + (waitForSsl != null ? waitForSsl.isDone() : "not Finished") + ":" + isSsl + ":"
499 + getControlChannel());
500 }
501 return isSsl;
502 }
503
504 public boolean isDataSsl() {
505 return isDataSsl;
506 }
507
508 public void setDataSsl(boolean isDataSsl) {
509 this.isDataSsl = isDataSsl;
510 }
511
512 }