View Javadoc
1   /*
2    * This file is part of Waarp Project (named also Waarp or GG).
3    *
4    *  Copyright (c) 2019, Waarp SAS, and individual contributors by the @author
5    *  tags. See the COPYRIGHT.txt in the distribution for a full listing of
6    * individual contributors.
7    *
8    *  All Waarp Project is free software: you can redistribute it and/or
9    * modify it under the terms of the GNU General Public License as published by
10   * the Free Software Foundation, either version 3 of the License, or (at your
11   * option) any later version.
12   *
13   * Waarp is distributed in the hope that it will be useful, but WITHOUT ANY
14   * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
15   * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
16   *
17   *  You should have received a copy of the GNU General Public License along with
18   * Waarp . If not, see <http://www.gnu.org/licenses/>.
19   */
20  package org.waarp.ftp.core.command.rfc2428;
21  
22  import org.waarp.common.command.ReplyCode;
23  import org.waarp.common.command.exception.Reply425Exception;
24  import org.waarp.common.logging.WaarpLogger;
25  import org.waarp.common.logging.WaarpLoggerFactory;
26  import org.waarp.ftp.core.command.AbstractCommand;
27  import org.waarp.ftp.core.config.FtpInternalConfiguration;
28  import org.waarp.ftp.core.data.FtpDataAsyncConn;
29  import org.waarp.ftp.core.utils.FtpChannelUtils;
30  
31  import java.net.InetAddress;
32  import java.net.InetSocketAddress;
33  
34  /**
35   * EPSV command
36   */
37  public class EPSV extends AbstractCommand {
38    /**
39     * Internal Logger
40     */
41    private static final WaarpLogger logger =
42        WaarpLoggerFactory.getLogger(EPSV.class);
43  
44    @Override
45    public final void exec() throws Reply425Exception {
46      // No Check if any argument
47      // Take a new port: 3 attempts
48      boolean isInit = false;
49      int newport = -1;
50      if (getSession().getDataConn().isPassiveMode()) {
51        // Previous mode was Passive so remove the current configuration
52        final InetSocketAddress local =
53            getSession().getDataConn().getLocalAddress();
54        final InetAddress remote =
55            getSession().getDataConn().getRemoteAddress().getAddress();
56        getConfiguration().delFtpSession(remote, local);
57      }
58      for (int i = 1; i <= FtpInternalConfiguration.RETRYNB; i++) {
59        newport = FtpDataAsyncConn.getNewPassivePort(getConfiguration());
60        if (newport == -1) {
61          throw new Reply425Exception("No port available");
62        }
63        logger.info("EPSV: set Passive Port {}", newport);
64        getSession().getDataConn().setLocalPort(newport);
65        getSession().getDataConn().setPassive();
66        // Init the connection
67        try {
68          if (getSession().getDataConn().initPassiveConnection()) {
69            isInit = true;
70            break;
71          }
72        } catch (final Reply425Exception e) {
73          logger.warn(
74              "EPSV refused at try: " + i + " with port: " + newport + " : {}",
75              e.getMessage());
76        }
77      }
78      if (!isInit) {
79        throw new Reply425Exception("Extended Passive mode not started");
80      }
81      // Return the address in Ftp format
82      final InetSocketAddress local =
83          getSession().getDataConn().getLocalAddress();
84      final String slocal = "Entering Extended Passive Mode (" +
85                            FtpChannelUtils.get2428Address(local) + ')';
86      final InetAddress remote =
87          getSession().getDataConn().getRemoteAddress().getAddress();
88      // Add the current FtpSession into the reference of session since the
89      // client will open the connection
90      getConfiguration().setNewFtpSession(remote, local, getSession());
91      getSession().setReplyCode(ReplyCode.REPLY_229_ENTERING_PASSIVE_MODE,
92                                "Entering Extended Passive Mode (|||" + newport +
93                                "|)");
94      logger.info("EPSV: answer ready on {}", slocal);
95      /*
96       * Could be:this.getFtpSession().setReplyCode(ReplyCode. REPLY_229_ENTERING_PASSIVE_MODE, slocal)
97       */
98    }
99  
100 }