NormalDataSocketFactory.java :  » UnTagged » swiftp » org » swiftp » Android Open Source

Android Open Source » UnTagged » swiftp 
swiftp » org » swiftp » NormalDataSocketFactory.java
/*
Copyright 2009 David Revell

This file is part of SwiFTP.

SwiFTP 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 3 of the License, or
(at your option) any later version.

SwiFTP 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 SwiFTP.  If not, see <http://www.gnu.org/licenses/>.
*/

package org.swiftp;

import java.io.IOException;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;

import android.util.Log;

public class NormalDataSocketFactory extends DataSocketFactory {
  /**
   * This class implements normal, traditional opening and closing of data sockets
   * used for transmitting directory listings and file contents. PORT and PASV
   * work according to the FTP specs. This is in contrast to a 
   * ProxyDataSocketFactory, which performs contortions to allow data sockets
   * to be proxied through a server out in the cloud.
   * 
   */
  
  // Listener socket used for PASV mode
  ServerSocket server = null;
  // Remote IP & port information used for PORT mode
  InetAddress remoteAddr;
  int remotePort;
  boolean isPasvMode = true;
  
  public NormalDataSocketFactory() {
    clearState();
  }
    
  
  private void clearState() {
    /**
     * Clears the state of this object, as if no pasv() or port() had occurred.
     * All sockets are closed.
     */
    if(server != null) {
      try {
        server.close();
      } catch (IOException e) {}
    }
    server = null;
    remoteAddr = null;
    remotePort = 0;
    myLog.l(Log.DEBUG, "NormalDataSocketFactory state cleared");
  }
  
  public int onPasv() {
    clearState();
    try {
      // Listen on any port (port parameter 0)
      server = new ServerSocket(0, Defaults.tcpConnectionBacklog);
      myLog.l(Log.DEBUG, "Data socket pasv() listen successful");
      return server.getLocalPort();
    } catch(IOException e) {
      myLog.l(Log.ERROR, "Data socket creation error");
      clearState();
      return 0;
    }
  }

  public boolean onPort(InetAddress remoteAddr, int remotePort) {
    clearState();
    this.remoteAddr = remoteAddr;
    this.remotePort = remotePort;
    return true;
  }
  
  public Socket onTransfer() {
    if(server == null) {
      // We're in PORT mode (not PASV)
      if(remoteAddr == null || remotePort == 0) {
        myLog.l(Log.INFO, "PORT mode but not initialized correctly");
        clearState();
        return null;
      }
      Socket socket;
      try {
        socket = new Socket(remoteAddr, remotePort);
      } catch (IOException e) {
        myLog.l(Log.INFO, 
            "Couldn't open PORT data socket to: " +
            remoteAddr.toString() + ":" + remotePort);
        clearState();
        return null;
      }
      
      // Kill the socket if nothing happens for X milliseconds
      try {
        socket.setSoTimeout(Defaults.SO_TIMEOUT_MS);
      } catch (Exception e) {
        myLog.l(Log.ERROR, "Couldn't set SO_TIMEOUT");
        clearState();
        return null;
      }
      
      return socket;
    } else {
      // We're in PASV mode (not PORT)
      Socket socket = null;
      try {
        socket = server.accept();
        myLog.l(Log.DEBUG, "onTransfer pasv accept successful");
      } catch (Exception e) {
        myLog.l(Log.INFO, "Exception accepting PASV socket");
        socket = null;
      }
      clearState();
      return socket;  // will be null if error occurred
    }
  }
  
  /**
   * Return the port number that the remote client should be informed of (in the body
   * of the PASV response).
   * @return The port number, or -1 if error.
   */
  public int getPortNumber() {
    if(server != null) {
      return server.getLocalPort(); // returns -1 if serversocket is unbound 
    } else {
      return -1;
    }
  }
  
  public InetAddress getPasvIp() {
    //String retVal = server.getInetAddress().getHostAddress();
    return FTPServerService.getWifiIp();
  }
  
  public void reportTraffic(long bytes) {
    // ignore, we don't care about how much traffic goes over wifi.
  }
}
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.