/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

package org.apache.ftpserver.impl;

import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketAddress;
import java.net.UnknownHostException;

import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;

import org.apache.ftpserver.DataConnectionConfiguration;
import org.apache.ftpserver.DataConnectionException;
import org.apache.ftpserver.ftplet.DataConnection;
import org.apache.ftpserver.ftplet.FtpException;
import org.apache.ftpserver.ssl.ClientAuth;
import org.apache.ftpserver.ssl.SslConfiguration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * <strong>Internal class, do not use directly.</strong>
 * 
 * We can get the FTP data connection using this class. It uses either PORT or PASV command.
 *
 * @author <a href="http://mina.apache.org">Apache MINA Project</a>
 */
public class IODataConnectionFactory implements ServerDataConnectionFactory {

    private final Logger LOG = LoggerFactory.getLogger(IODataConnectionFactory.class);

    private FtpServerContext serverContext;

    private Socket dataSoc;

    ServerSocket servSoc;

    InetAddress address;

    int port = 0;

    long requestTime = 0L;

    boolean passive = false;

    boolean secure = false;

    private boolean isZip = false;

    InetAddress serverControlAddress;

    FtpIoSession session;

    public IODataConnectionFactory(final FtpServerContext serverContext, final FtpIoSession session) {
        this.session = session;
        this.serverContext = serverContext;
        if ((session != null) && (session.getListener() != null) && session.getListener().getDataConnectionConfiguration().isImplicitSsl()) {
            secure = true;
        }
    }

    /**
     * Close data socket. This method must be idempotent as we might call it multiple times during disconnect.
     */
    public synchronized void closeDataConnection() {

    // close client socket if any
    if (dataSoc != null) {
        try {
        dataSoc.close();
        } catch (Exception ex) {
        LOG.warn("FtpDataConnection.closeDataSocket()", ex);
        }
        dataSoc = null;
    }

    // close server socket if any
    if (servSoc != null) {
        try {
        servSoc.close();
        } catch (Exception ex) {
        LOG.warn("FtpDataConnection.closeDataSocket()", ex);
        }

        if (session != null) {
        DataConnectionConfiguration dcc = session.getListener().getDataConnectionConfiguration();
        if (dcc != null) {
            dcc.releasePassivePort(port);
        }
        }

        servSoc = null;
    }

    // reset request time
    requestTime = 0L;
    }

    /**
     * Port command.
     */
    public synchronized void initActiveDataConnection(final InetSocketAddress address) {
        // close old sockets if any
        closeDataConnection();
    
        // set variables
        passive = false;
        this.address = address.getAddress();
        port = address.getPort();
        requestTime = System.currentTimeMillis();
        }
    
        private SslConfiguration getSslConfiguration() {
        DataConnectionConfiguration dataCfg = session.getListener().getDataConnectionConfiguration();
    
        SslConfiguration configuration = dataCfg.getSslConfiguration();
    
        // fall back if no configuration has been provided on the data connection config
        if (configuration == null) {
            configuration = session.getListener().getSslConfiguration();
        }
    
        return configuration;
    }

    /**
     * Initiate a data connection in passive mode (server listening).
     */
    public synchronized InetSocketAddress initPassiveDataConnection() throws DataConnectionException {
        LOG.debug("Initiating passive data connection");
        // close old sockets if any
        closeDataConnection();
    
        // get the passive port
        int passivePort = session.getListener().getDataConnectionConfiguration().requestPassivePort();
        if (passivePort == -1) {
            servSoc = null;
            throw new DataConnectionException("Cannot find an available passive port.");
        }
    
        // open passive server socket and get parameters
        try {
            DataConnectionConfiguration dataCfg = session.getListener().getDataConnectionConfiguration();
    
            String passiveAddress = dataCfg.getPassiveAddress();
    
            if (passiveAddress == null) {
                address = serverControlAddress;
            } else {
                address = resolveAddress(dataCfg.getPassiveAddress());
            }
    
            if (secure) {
                LOG.debug("Opening SSL passive data connection on address \"{}\" and port {}", address, passivePort);
                SslConfiguration ssl = getSslConfiguration();
                
                if (ssl == null) {
                    throw new DataConnectionException("Data connection SSL required but not configured.");
                }
        
                // this method does not actually create the SSL socket, due to a JVM bug
                // (https://issues.apache.org/jira/browse/FTPSERVER-241).
                // Instead, it creates a regular
                // ServerSocket that will be wrapped as a SSL socket in createDataSocket()
                servSoc = new ServerSocket(passivePort, 0, address);
                LOG.debug("SSL Passive data connection created on address \"{}\" and port {}", address, passivePort);
            } else {
                LOG.debug("Opening passive data connection on address \"{}\" and port {}", address, passivePort);
                servSoc = new ServerSocket(passivePort, 0, address);
                LOG.debug("Passive data connection created on address \"{}\" and port {}", address, passivePort);
            }
            
            port = servSoc.getLocalPort();
            servSoc.setSoTimeout(dataCfg.getIdleTime() * 1000);
    
            // set different state variables
            passive = true;
            requestTime = System.currentTimeMillis();
    
            return new InetSocketAddress(address, port);
        } catch (Exception ex) {
            closeDataConnection();
            throw new DataConnectionException("Failed to initate passive data connection: " + ex.getMessage(), ex);
        }
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.apache.ftpserver.FtpDataConnectionFactory2#getInetAddress()
     */
    public InetAddress getInetAddress() {
        return address;
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.apache.ftpserver.FtpDataConnectionFactory2#getPort()
     */
    public int getPort() {
        return port;
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.apache.ftpserver.FtpDataConnectionFactory2#openConnection()
     */
    public DataConnection openConnection() throws Exception {
        return new IODataConnection(createDataSocket(), session, this);
    }

    /**
     * Get the data socket. In case of error returns null.
     */
    private synchronized Socket createDataSocket() throws Exception {
        // get socket depending on the selection
        dataSoc = null;
        DataConnectionConfiguration dataConfig = session.getListener().getDataConnectionConfiguration();
        try {
            if (!passive) {
                if (secure) {
                    LOG.debug("Opening secure active data connection");
                    SslConfiguration ssl = getSslConfiguration();
                    
                    if (ssl == null) {
                        throw new FtpException("Data connection SSL not configured");
                    }
        
                    // get socket factory
                    SSLSocketFactory socFactory = ssl.getSocketFactory();
        
                    // create socket
                    SSLSocket ssoc = (SSLSocket) socFactory.createSocket();
                    ssoc.setUseClientMode(false);
        
                    // initialize socket
                    if (ssl.getEnabledCipherSuites() != null) {
                        ssoc.setEnabledCipherSuites(ssl.getEnabledCipherSuites());
                    }
        
                    if (ssl.getEnabledProtocols() != null) {
                        ssoc.setEnabledProtocols(ssl.getEnabledProtocols());
                    }
                    
                    dataSoc = ssoc;
                } else {
                    LOG.debug("Opening active data connection");
                    dataSoc = new Socket();
                }
        
                dataSoc.setReuseAddress(true);
        
                InetAddress localAddr = resolveAddress(dataConfig.getActiveLocalAddress());
        
                // if no local address has been configured, make sure we use the same as the client connects from
                if (localAddr == null) {
                    localAddr = ((InetSocketAddress) session.getLocalAddress()).getAddress();
                }
        
                SocketAddress localSocketAddress = new InetSocketAddress(localAddr, dataConfig.getActiveLocalPort());
        
                LOG.debug("Binding active data connection to {}", localSocketAddress);
                dataSoc.bind(localSocketAddress);
        
                dataSoc.connect(new InetSocketAddress(address, port));
            } else {
    
            if (secure) {
                LOG.debug("Opening secure passive data connection");
                // this is where we wrap the unsecured socket as a SSLSocket. This is
                // due to the JVM bug described in FTPSERVER-241.
    
                // get server socket factory
                SslConfiguration ssl = getSslConfiguration();
    
                // we've already checked this, but let's do it again
                if (ssl == null) {
                throw new FtpException("Data connection SSL not configured");
                }
    
                SSLSocketFactory ssocketFactory = ssl.getSocketFactory();
    
                Socket serverSocket = servSoc.accept();
    
                SSLSocket sslSocket = (SSLSocket) ssocketFactory.createSocket(serverSocket, serverSocket.getInetAddress().getHostAddress(), serverSocket.getPort(), true);
                sslSocket.setUseClientMode(false);
    
                // initialize server socket
                if (ssl.getClientAuth() == ClientAuth.NEED) {
                    sslSocket.setNeedClientAuth(true);
                } else if (ssl.getClientAuth() == ClientAuth.WANT) {
                    sslSocket.setWantClientAuth(true);
                }
    
                if (ssl.getEnabledCipherSuites() != null) {
                    sslSocket.setEnabledCipherSuites(ssl.getEnabledCipherSuites());
                }
    
                if (ssl.getEnabledProtocols() != null) {
                    sslSocket.setEnabledProtocols(ssl.getEnabledProtocols());
                }
    
                dataSoc = sslSocket;
            } else {
                LOG.debug("Opening passive data connection");
    
                dataSoc = servSoc.accept();
            }
    
            if (dataConfig.isPassiveIpCheck()) {
                // Let's make sure we got the connection from the same
                // client that we are expecting
                InetAddress remoteAddress = ((InetSocketAddress) session.getRemoteAddress()).getAddress();
                InetAddress dataSocketAddress = dataSoc.getInetAddress();
                if (!dataSocketAddress.equals(remoteAddress)) {
                LOG.warn("Passive IP Check failed. Closing data connection from " + dataSocketAddress + " as it does not match the expected address " + remoteAddress);
                closeDataConnection();
                return null;
                }
            }
    
            DataConnectionConfiguration dataCfg = session.getListener().getDataConnectionConfiguration();
    
            dataSoc.setSoTimeout(dataCfg.getIdleTime() * 1000);
            LOG.debug("Passive data connection opened");
            }
        } catch (Exception ex) {
            closeDataConnection();
            LOG.warn("FtpDataConnection.getDataSocket()", ex);
            throw ex;
        }
        dataSoc.setSoTimeout(dataConfig.getIdleTime() * 1000);
    
        // Make sure we initiate the SSL handshake, or we'll
        // get an error if we turn out not to send any data
        // e.g. during the listing of an empty directory
        if (dataSoc instanceof SSLSocket) {
            ((SSLSocket) dataSoc).startHandshake();
        }
    
        return dataSoc;
    }

    /*
     * (non-Javadoc) Returns an InetAddress object from a hostname or IP address.
     */
    private InetAddress resolveAddress(String host) throws DataConnectionException {
        if (host == null) {
            return null;
        } else {
            try {
            return InetAddress.getByName(host);
            } catch (UnknownHostException ex) {
            throw new DataConnectionException("Failed to resolve address", ex);
            }
        }
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.apache.ftpserver.DataConnectionFactory#isSecure()
     */
    public boolean isSecure() {
    return secure;
    }

    /**
     * Set the security protocol.
     */
    public void setSecure(final boolean secure) {
    this.secure = secure;
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.apache.ftpserver.DataConnectionFactory#isZipMode()
     */
    public boolean isZipMode() {
    return isZip;
    }

    /**
     * Set zip mode.
     */
    public void setZipMode(final boolean zip) {
    isZip = zip;
    }

    /**
     * Check the data connection idle status.
     */
    public synchronized boolean isTimeout(final long currTime) {

    // data connection not requested - not a timeout
    if (requestTime == 0L) {
        return false;
    }

    // data connection active - not a timeout
    if (dataSoc != null) {
        return false;
    }

    // no idle time limit - not a timeout
    int maxIdleTime = session.getListener().getDataConnectionConfiguration().getIdleTime() * 1000;
    if (maxIdleTime == 0) {
        return false;
    }

    // idle time is within limit - not a timeout
    if ((currTime - requestTime) < maxIdleTime) {
        return false;
    }

    return true;
    }

    /**
     * Dispose data connection - close all the sockets.
     */
    public void dispose() {
    closeDataConnection();
    }

    /**
     * Sets the server's control address.
     */
    public void setServerControlAddress(final InetAddress serverControlAddress) {
    this.serverControlAddress = serverControlAddress;
    }
}
