Package xnap.plugin.nap.net

Source Code of xnap.plugin.nap.net.Upload

/*
*  XNap
*
*  A pure java file sharing client.
*
*  See AUTHORS for copyright information.
*
*  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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*
*/
package xnap.plugin.nap.net;

import xnap.io.*;
import xnap.net.*;
import xnap.plugin.nap.Plugin;
import xnap.plugin.nap.net.msg.MessageHandler;
import xnap.plugin.nap.net.msg.client.AcceptFailedMessage;
import xnap.plugin.nap.net.msg.client.PrivateMessage;
import xnap.plugin.nap.net.msg.client.UploadAckMessage;
import xnap.plugin.nap.net.msg.client.UploadCompleteMessage;
import xnap.plugin.nap.net.msg.client.UploadingFileMessage;
import xnap.plugin.nap.net.msg.server.AltDownloadAckMessage;
import xnap.plugin.nap.net.msg.server.MessageListener;
import xnap.plugin.nap.net.msg.server.ServerMessage;
import xnap.plugin.nap.util.NapFileHelper;
import xnap.plugin.nap.util.NapPreferences;
import xnap.util.*;

import java.io.*;
import java.net.*;
import java.util.*;

/**
* Handles both normal and firewalled uploads.
*/
public class Upload extends AbstractUpload implements MessageListener
{

    //--- Constant(s) ---
   
    /**
     * Socket timeout during connect.
     */
    public static final int CONNECT_TIMEOUT = 1 * 60 * 1000;
   
    //--- Data field(s) ---

    protected Server server;

    protected Socket socket;
    protected InputStream in;
    protected OutputStream out;
    protected String requestFilename;
   
    protected String host;
    protected int port;
    private Object lock = new Object();

    //--- Constructor(s) ---
    public Upload(String nick, File file, Server server, String filename)
    {
    super(server.getUser(nick));

    this.file = file;
    this.server = server;
    this.requestFilename = filename;
    }

    //--- Method(s) ---

    /**
     * Sends <code>UploadAckMessage</code> to server and waits CONNECT_TIMEOUT
     * secs for an upload socket.
     */
    public void connect() throws IOException
    {
    if (!server.isConnected()) {
      throw new IOException(Plugin.tr("Server disconnected"));
  }
 
    if (!server.getUser(getUser().getName()).isAllowedToDownload()) {
      throw new IOException(Plugin.tr("Leecher rejected"));
  }
 
    MessageHandler.subscribe(AltDownloadAckMessage.TYPE, this);
   
    MessageHandler.send
      (server, new UploadAckMessage(user.getName(), requestFilename));

    UploadSocket us = null;
 
  /* if user is not firewalled wait for a socket, this does not impede
           the peer from sending an alternate dl request anyway.  */
  if (server.getLocalPort() != 0) {
      us = new UploadSocket(getUser().getName(), requestFilename);
      us = (UploadSocket)server.getListener().waitForSocket
    (us, CONNECT_TIMEOUT);
  }
  else {
      synchronized(lock) {
    try {
        lock.wait(CONNECT_TIMEOUT);
    }
    catch (InterruptedException e) {
    }
      }
  }

  MessageHandler.unsubscribe(AltDownloadAckMessage.TYPE, this);
 
  /* while we wait for an upload socket an AltDownloadAckMessage could
           come in to signal a firewalled upload, we check for both.  */
  if (us == null && host == null && port == 0) {
      throw new IOException(Plugin.tr("Listener timeout"));
  }

  // check again in case whois info wasn't ready yet
  if (!server.getUser(getUser().getName()).isAllowedToDownload()) {
      if (us != null) {
    if (us.socket != null) {
        us.socket.close();
    }
      }
      throw new IOException(Plugin.tr("Leecher rejected"));
  }

  if (us != null) {
      socket = us.socket;
      try {
    socket.setSoTimeout(CONNECT_TIMEOUT);
      }
      catch (SocketException s) {
      }
      offset = us.offset;
      try {
    out = new ThrottledOutputStream(socket.getOutputStream());
    establishStream();
      }
      catch (IOException ie) {
    close(false);
    throw(ie);
      }
  }
  else {
      try {
    //socket = new Socket(host, port);
    socket = NetHelper.connect(host, port, CONNECT_TIMEOUT);
    try {
        socket.setSoTimeout(CONNECT_TIMEOUT);
    }
    catch (SocketException s) {
    }
    in = new BufferedInputStream(socket.getInputStream());
    out = new ThrottledOutputStream(socket.getOutputStream());
    establishReverseStream();
      }
      catch (IOException ie) {
    close(false);
    throw(ie);
      }
  }

  MessageHandler.send(new UploadingFileMessage());
    }

    public void close(boolean sendMsg)
    {
  if (sendMsg) {
      MessageHandler.send(new UploadCompleteMessage());
  }

        try {
      if (in != null)
    in.close();
      if (out != null)
    out.close();
      if (socket != null)
    socket.close();
        }
  catch (IOException e) {
        }
    }

    public void close()
    {
  close(true);
    }

    /**
     * Changed implementation: <code>equals</code> is called before adding a
     * new upload to the {@link UploadQueue} to check if it's not already
     * there.  */
    public boolean equals(Object o)
    {
  if (o instanceof Upload) {
      Upload u = (Upload)o;

      // we don't check the server yet
      return (file.equals(u.getFile()) && user.equals(u.getUser()));
     
      //  Socket s = u.getSocket();
//        return ((s != null
//           && getSocket().getInetAddress().equals(s.getInetAddress())
//           && getSocket().getPort() == s.getPort()));
  }
  return false;
    }

    /**
     * Needed for equals.
     */
    public Socket getSocket()
    {
  return socket;
    }

    public void reject()
    {
  MessageHandler.send(server,
          new AcceptFailedMessage(getUser().getName(),
                requestFilename));
    }

    public void write(byte[] b, int len) throws IOException
    {
  out.write(b, 0, len);
    }

    /**
     * Most of the <code>establishStream()</code> is in the {@link
     * UploadSocket} class which is not that beautiful. This problem should be
     * tackled.  */
    protected void establishStream() throws IOException
    {
  if (file == null) {
      String response = "INVALID REQUEST";
      out.write(response.getBytes());
      throw new IOException(Plugin.tr("Invalid request"));
  }

  out.write((new Long(file.length())).toString().getBytes());
   

    /**
     * Makes {@link AltUpload} futile. This is necessary since the decision
     * whether it is a normal upload or a firewalled upload is done rather
     * late.  */
    protected void establishReverseStream() throws IOException
    {
  String message;

  // read magic number '1'
  char c = (char)in.read();
  if (c != '1') {
      throw new IOException(Plugin.tr("Invalid request"));
  }
 
  message = "SEND";
  out.write(message.getBytes());
  out.flush();
 
  message = server.getUsername() + " \"" + requestFilename
      + "\" " + file.length();
  Debug.log("nap ul: -> " + message);
  out.write(message.getBytes());
  out.flush();

  byte data[] = new byte[1000];
  int j = in.read(data);
 
  if (j <= 0) {
      throw new IOException(Plugin.tr("Socket error"));
  }

  String response = new String(data, 0, j);
  Debug.log("nap ul: <- " + response);
  try {
      offset = Long.parseLong(response);
  }
  catch (NumberFormatException e) {
      Debug.log(e);
      throw new IOException(Plugin.tr("Invalid request"));
  }   
 
  Debug.log("nap ul: offset <- " + response);
    }

    public void messageReceived(ServerMessage msg)
    {
  if (msg instanceof AltDownloadAckMessage) {
      AltDownloadAckMessage m = (AltDownloadAckMessage)msg;

      if (m.nick.equals(user.getName())
    && m.filename.equals(requestFilename)) {
    m.consume();
    host = m.ip;
    port = m.port;

    // wake up thread waiting in connect()
    synchronized (lock) {
        lock.notify();
    }
      }
  }
    }
}
TOP

Related Classes of xnap.plugin.nap.net.Upload

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.