/* * Copyright (C) 2006-2008 Alfresco Software Limited. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * As a special exception to the terms and conditions of version 2.0 of * the GPL, you may redistribute this Program in connection with Free/Libre * and Open Source Software ("FLOSS") applications as described in Alfresco's * FLOSS exception. You should have recieved a copy of the text describing * the FLOSS exception, and it is also available here: * http://www.alfresco.com/legal/licensing" */ package org.alfresco.jlan.ftp; import java.io.IOException; import java.net.InetAddress; import java.net.ServerSocket; import java.net.Socket; import java.net.UnknownHostException; /** * FTP Data Session Class * * <p>A data connection is made when a PORT or PASV FTP command is received on the main control session. * * <p>The PORT command will actively connect to the specified address/port on the client. The PASV command will create a * listening socket and wait for the client to connect. * * @author gkspencer */ public class FTPDataSession implements Runnable { // FTP session that this data connection is associated with private FTPSrvSession m_cmdSess; // Connection details for active connection private InetAddress m_clientAddr; private int m_clientPort; // Local port to use private int m_localPort; // Active data session socket private Socket m_activeSock; // Passive data session socket private ServerSocket m_passiveSock; // Adapter to bind the passive socket to private InetAddress m_bindAddr; // Transfer in progress and abort file transfer flags private boolean m_transfer; private boolean m_abort; // Send/receive data byte count private long m_bytCount; /** * Class constructor * * <p>Create a data connection that listens for an incoming connection. * * @param sess FTPSrvSession * @exception IOException */ protected FTPDataSession(FTPSrvSession sess) throws IOException { // Set the associated command session m_cmdSess = sess; // Create a server socket to listen for the incoming connection m_passiveSock = new ServerSocket(0, 1, null); } /** * Class constructor * * <p>Create a data connection that listens for an incoming connection on the specified * network adapter and local port. * * @param sess FTPSrvSession * @param localPort int * @param bindAddr InetAddress * @exception IOException */ protected FTPDataSession(FTPSrvSession sess, int localPort, InetAddress bindAddr) throws IOException { // Set the associated command session m_cmdSess = sess; // Create a server socket to listen for the incoming connection on the specified network adapter m_localPort = localPort; m_passiveSock = new ServerSocket(localPort, 1, bindAddr); } /** * Class constructor * * <p>Create a data connection that listens for an incoming connection on the specified * network adapter. * * @param sess FTPSrvSession * @param bindAddr InetAddress * @exception IOException */ protected FTPDataSession(FTPSrvSession sess, InetAddress bindAddr) throws IOException { // Set the associated command session m_cmdSess = sess; // Create a server socket to listen for the incoming connection on the specified network adapter m_passiveSock = new ServerSocket(0, 1, bindAddr); } /** * Class constructor * * <p>Create a data connection to the specified client address and port. * * @param sess FTPSrvSession * @param addr InetAddress * @param port int */ protected FTPDataSession(FTPSrvSession sess, InetAddress addr, int port) { // Set the associated command session m_cmdSess = sess; // Save the client address/port details, the actual connection will be made later when // the client requests/sends a file m_clientAddr = addr; m_clientPort = port; } /** * Class constructor * * <p>Create a data connection to the specified client address and port, using the specified local * port. * * @param sess FTPSrvSession * @param localPort int * @param addr InetAddress * @param port int */ protected FTPDataSession(FTPSrvSession sess, int localPort, InetAddress addr, int port) { // Set the associated command session m_cmdSess = sess; // Save the local port m_localPort = localPort; // Save the client address/port details, the actual connection will be made later when // the client requests/sends a file m_clientAddr = addr; m_clientPort = port; } /** * Return the associated command session * * @return FTPSrvSession */ public final FTPSrvSession getCommandSession() { return m_cmdSess; } /** * Return the local port * * @return int */ public final int getLocalPort() { if ( m_passiveSock != null) return m_passiveSock.getLocalPort(); else if ( m_activeSock != null) return m_activeSock.getLocalPort(); return -1; } /** * Return the port that was allocated to the data session * * @return int */ protected final int getAllocatedPort() { return m_localPort; } /** * Return the passive server socket address * * @return InetAddress */ public final InetAddress getPassiveAddress() { if ( m_passiveSock != null) { // Get the server socket local address InetAddress addr = m_passiveSock.getInetAddress(); if ( addr.getHostAddress().compareTo("0.0.0.0") == 0) { try { addr = InetAddress.getLocalHost(); } catch (UnknownHostException ex) { } } return addr; } return null; } /** * Return the passive server socket port * * @return int */ public final int getPassivePort() { if ( m_passiveSock != null) return m_passiveSock.getLocalPort(); return -1; } /** * Determine if a file transfer is active * * @return boolean */ public final boolean isTransferActive() { return m_transfer; } /** * Abort an in progress file transfer */ public final void abortTransfer() { m_abort = true; } /** * Return the transfer byte count * * @return long */ public final synchronized long getTransferByteCount() { return m_bytCount; } /** * Return the data socket connected to the client * * @return Socket * @exception IOException */ public final Socket getSocket() throws IOException { // Check for a passive connection, get the incoming socket connection if ( m_passiveSock != null) m_activeSock = m_passiveSock.accept(); else { if ( m_localPort != 0) { // Use the specified local port m_activeSock = new Socket(m_clientAddr, m_clientPort, null, m_localPort); } else m_activeSock = new Socket(m_clientAddr, m_clientPort); } // Set the socket to close immediately m_activeSock.setSoLinger(false, 0); // Return the data socket return m_activeSock; } /** * Close the data connection */ public final void closeSession() { // If the data connection is active close it if ( m_activeSock != null) { try { m_activeSock.close(); } catch (Exception ex) { } m_activeSock = null; } // Close the listening socket for a passive connection if ( m_passiveSock != null) { try { m_passiveSock.close(); } catch (Exception ex) { } m_passiveSock = null; } } /** * Run a file send/receive in a seperate thread */ public void run() { } }