Package xnap.plugin.gift.net

Source Code of xnap.plugin.gift.net.Engine

/*
*  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.gift.net;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Enumeration;
import java.util.EventListener;
import java.util.Hashtable;
import java.util.Vector;

import xnap.XNap;
import xnap.net.IUser;
import xnap.plugin.gift.net.event.*;
import xnap.plugin.gift.net.event.listener.DebugEventListener;
import xnap.plugin.gift.net.event.listener.ErrorEventListener;
import xnap.plugin.gift.net.event.listener.NetworkEventListener;
import xnap.plugin.gift.net.event.listener.SharesEventListener;
import xnap.plugin.gift.net.lexer.Command;
import xnap.plugin.gift.net.lexer.StreamLexer;
import xnap.util.DownloadQueue;


/**
* Engine
*
* @author <a href="mailto:tvanlessen@taval.de">Tammo van Lessen</a>
* @version CVS $Id: Engine.java,v 1.12 2003/03/22 01:29:31 taval Exp $
*/
public class Engine
{
    //~ Static fields/initializers ---------------------------------------------

    public static final int OFFLINE = 0;
    public static final int CONNECTING = 1;
    public static final int ONLINE = 2;
    private static final long NETWORK_STATS_INTERVAL = 180 * 1000; // 3 min
    private static Engine singleton;

    //~ Instance fields --------------------------------------------------------

    long NetworkStatsTimer = 0;
    private Hashtable downloads;
    private Hashtable searches;
    private Hashtable stats;
    private InetAddress host;
    private Socket socket;
    private StreamLexer lexer;
    private String serverName;
    private String serverVersion;
    private String user = null;
    private Thread processingThread;
    private Vector listeners;
    private Vector outQueue;
    private boolean debug = false;
    private boolean exitProcessThread;
    private int connectState = OFFLINE;
    private int port;

    //~ Constructors -----------------------------------------------------------

    /**
     * Creates a new Engine object.
     */
    private Engine()
    {
        outQueue = new Vector();
        listeners = new Vector();
        searches = new Hashtable();
        downloads = new Hashtable();
        stats = new Hashtable();
        host = null;
        port = -1;
        processingThread = null;
    }

    //~ Methods ----------------------------------------------------------------

    /**
     * Singleton getInstance()
     *
     * @return Engine
     */
    public static synchronized Engine getInstance()
    {
        if (singleton == null) {
            singleton = new Engine();
        }

        return singleton;
    }

    /**
     * Returns true if Engine is connected to giFT server
     *
     * @return boolean
     */
    public boolean isConnected()
    {
        return (connectState == ONLINE);
    }

    /**
     * Returns true if Engine is connecting to giFT server (time between
     * physically connect and the attach-response)
     *
     * @return boolean
     */
    public boolean isConnecting()
    {
        return (connectState == CONNECTING);
    }

    /**
     * Enables debuging events
     *
     * @param debug
     */
    public void setDebug(boolean debug)
    {
        this.debug = debug;
    }

    /**
     * Returns true is debugging is enabled
     *
     * @return boolean
     */
    public boolean getDebug()
    {
        return debug;
    }

    /**
     * Sets giFT host
     *
     * @param host
     */
    public void setHost(String host)
    {
        try {
            this.host = InetAddress.getByName(host);
        } catch (UnknownHostException e) {
            fireEvent(new ErrorEvent(e));
        }
    }

    /**
     * Sets giFT port
     *
     * @param port
     */
    public void setPort(int port)
    {
        this.port = port;
    }

    /**
     * Returns count of active searches
     *
     * @return count
     */
    public int getSearchCount()
    {
        return searches.size();
    }

    /**
     * Returns giFT server's name and version as String
     *
     * @return server info
     */
    public String getServerInfo()
    {
        return serverName + " (" + serverVersion + ")";
    }

    /**
     * Returns giFT statistics as String
     *
     * @return stats
     */
    public String getStats()
    {
        String str = "";
        Enumeration keys = stats.keys();

        while (keys.hasMoreElements()) {
            String key = (String) keys.nextElement();
            str += ("(" + key + ": " + (String) stats.get(key) + ")");
        }

        return str;
    }

    /**
     * Sets giFT user name
     *
     * @param user
     */
    public void setUserName(String user)
    {
        this.user = user;
    }

    /**
     * Returns giFT user name
     *
     * @return user name
     */
    public String getUserName()
    {
        return user;
    }

    /**
     * Forces giFT to send network stats
     */
    public synchronized void UpdateNetworkStats()
    {
        if (!isConnected()) {
            return;
        }

        Command cmd = new Command("stats");
        queueCommand(cmd);
    }

    //TODO!!!!!!!
    public void addDownload(SearchResult sr)
    {
        if (!isConnected()) {
            return;
        }

        Command cmd = new Command("addsource");
        cmd.addKey("hash", sr.getHash());
        cmd.addKey("size", Long.toString(sr.getFilesize()));
        cmd.addKey("url", sr.getUrl());
        cmd.addKey("user", ((User) sr.getUser()).getGiFTName());
        // TODO
        cmd.addKey("save", sr.getShortFilename());
        queueCommand(cmd);
    }

  public void changeDownload(DownloadContainer dc, String action)
  {
    if (!isConnected()) {
      return;
    }
    if (downloads.get(dc) == null) {
      return;
    }
    Command cmd = new Command("transfer");
    cmd.setCommandArgument((String)downloads.get(dc));
    cmd.addKey("action", action);
    queueCommand(cmd)
  }
 
  public void changeSearch(Search s, String action)
  {
    if (!isConnected()) {
      return;
    }
    if (searches.get(s) == null) {
      return;
    }
    Command cmd = new Command("search");
    cmd.setCommandArgument((String)searches.get(s));
    cmd.addKey("action", action);
    queueCommand(cmd);
    System.out.println(cmd.print());
  }

    /**
     * Adds event listener
     *
     * @param listener
     */
    public void addEventListener(EventListener listener)
    {
        listeners.add(listener);
    }

    /**
     * Quits giFT (process)
     */
    public void quitGiFT()
    {
        if (!isConnected()) {
            return;
        }

    Command cmd = new Command("quit");
    try {
      OutputStream os = socket.getOutputStream();
      os.write(cmd.print().getBytes());
      os.flush();
    } catch (Exception e) {}
    try {
      socket.close();
    } catch (IOException e) {}
    socket = null;
    processingThread = null;
    if (connectState == ONLINE) {
      connectState = OFFLINE;
      fireEvent(new OfflineEvent());
    }
    }

    /**
     * Removes an event listener
     *
     * @param listener
     */
    public void removeEventListener(EventListener listener)
    {
        listeners.remove(listener);
    }

    /**
     * Adds a new search
     *
     * @param sf SearchFilter
     */
    public void search(Search s)
    {
        if (!isConnected()) {
            return;
        }

        searches.put(Integer.toString(s.hashCode()), s);
    searches.put(s, Integer.toString(s.hashCode()));
        Command cmd = new Command("search");
        cmd.setCommandArgument(Integer.toString(s.hashCode()));
        cmd.addKey("query", s.getSearchFilter().getSearchText());
        queueCommand(cmd);
        s.searchStarted(new SearchControlEvent(ControlEvent.STARTED));
    }

    /**
     * Starts the engine
     */
    public void start()
    {
        if ((host == null) || (port == -1)) {
            fireEvent(new ErrorEvent("host or port not set!"));

            return;
        }

        if (isConnected()) {
            return;
        }

        outQueue.clear();
        searches.clear();
        downloads.clear();
        stats.clear();
        exitProcessThread = false;
    processingThread = new Thread("GiFTEngine") {
          public void run()
          {
            process();
          }
        };
        processingThread.start();
    }

    /**
     * Stops the engine
     */
    public void stop()
    {
        if (!isConnected()) {
            return;
        }

        // TODO: use 'quit' if giFT has been started by NXap
        Command cmd = new Command("detach");
        try {
          OutputStream os = socket.getOutputStream();
          os.write(cmd.print().getBytes());
          os.flush();
        } catch (Exception e) {}
    try {
      socket.close();
    } catch (IOException e) {}
    socket = null;
    processingThread = null;
    if (connectState == ONLINE) {
      connectState = OFFLINE;
      fireEvent(new OfflineEvent());
    }
    }

    /**
     * Forces giFT to sync its shares index
     */
    public void syncShares()
    {
        if (!isConnected()) {
            return;
        }

        Command cmd = new Command("share");
        cmd.addKey("action", "sync");
        queueCommand(cmd);
        fireEvent(new SharesControlEvent(SharesControlEvent.SYNC_STARTED));
    }

    /**
     * Forces giFT to list its shares
     */
    public void updateShareListing()
    {
        if (!isConnected()) {
            return;
        }

        queueCommand(new Command("shares"));
        fireEvent(new SharesControlEvent(ControlEvent.STARTED));
    }

    /*
     * Dispatches incomming commands
     *
     * TODO: Implement the following
     *                 SHARES,         SHARE, all upload stuff
     *
     *
     *
     */
    private synchronized void dispatchCommand(Command cmd)
    {
        if (cmd.getCommand().equalsIgnoreCase("ATTACH")) {
            connectState = ONLINE;

            serverName = cmd.getKey("server");
            serverVersion = cmd.getKey("version");
            fireEvent(new OnlineEvent(serverName, serverVersion));
            UpdateNetworkStats();
            NetworkStatsTimer = System.currentTimeMillis() + (15 * 1000); // 15 sec

            return;
        } else if (cmd.getCommand().equalsIgnoreCase("STATS")) {
            Vector subCommands = cmd.getSubCommands();
            stats.clear();
      for (int i = 0; i < subCommands.size(); i++) {
                Command proto = (Command)subCommands.get(i);
                long files = -1;
                long users = -1;
                float size = -1;

                try {
                    files = Long.parseLong((String) proto.getKey("files"));
                } catch (NumberFormatException e) {
                }

                try {
                    users = Long.parseLong((String) proto.getKey("users"));
                } catch (NumberFormatException e) {
                }

                try {
                    size = Float.parseFloat((String) proto.getKey("size"));
                } catch (NumberFormatException e) {
                }

                if (!proto.getCommand().equalsIgnoreCase("gift")) {
                    stats.put(proto.getCommand(),
                        files + XNap.tr("Files", 1, 0) + ", " + users +
                        XNap.tr("Users", 1, 0) + ", " + size + " GB");
                }

                StatsEvent nsevt = new StatsEvent(proto.getCommand());
                nsevt.setFiles(files);
                nsevt.setUsers(users);
                nsevt.setSize(size);
                fireEvent(nsevt);
            }

            return;
        } else if (cmd.getCommand().equalsIgnoreCase("ITEM")) {
            // if share item
            if (cmd.getCommandArgument() == null) {
                if (cmd.hasKeys()) {
                    ShareItemEvent se = new ShareItemEvent();
                    se.setPath(cmd.getKey("path"));

                    try {
                        se.setSize(Long.parseLong(cmd.getKey("size")));
                    } catch (Exception e) {
                    }

                    se.setMime(cmd.getKey("mime"));
                    se.setHash(cmd.getKey("hash"));

                    Command meta = cmd.getSubCommandByName("META");

                    if (meta != null) {
                        Enumeration keys = meta.getKeys();

                        while (keys.hasMoreElements()) {
                            String key = (String) keys.nextElement();
                            se.addMetaItem(key, meta.getKey(key));
                        }
                    }

                    fireEvent(se);
                } else {
                    fireEvent(new SharesControlEvent(ControlEvent.FINISHED));
                }
            } else {
                if (cmd.hasKeys()) {
                    // search item
                    long size = -1;

                    try {
                        size = Long.parseLong(cmd.getKey("size"));
                    } catch (Exception e) {
                    }

                    int score = 1;

                    try {
                        score = Integer.parseInt(cmd.getKey("availability"));
                    } catch (Exception e) {
                    }

                    Hashtable meta = new Hashtable();

                    Command metaCmd = cmd.getSubCommandByName("META");

                    if (metaCmd != null) {
                        Enumeration keys = metaCmd.getKeys();

                        while (keys.hasMoreElements()) {
                            String key = (String) keys.nextElement();
                            meta.put(key, metaCmd.getKey(key));
                        }
                    }

                    IUser user = new User(cmd.getKey("user"));
                    SearchResult sr = new SearchResult(size, user,
                            cmd.getKey("file"), cmd.getKey("hash"),
                            cmd.getKey("node"), cmd.getKey("mime"),
                            cmd.getKey("url"), score, meta);
          Search search = (Search) searches.get(cmd.getCommandArgument());
          search.searchItemReceived(new SearchItemEvent(search.getSearchFilter(),sr));
                } else {
                    //search finished
          Search search = (Search) searches.remove(cmd.getCommandArgument());
          search.searchFinished(new SearchControlEvent(ControlEvent.FINISHED));
                }
            }
        } else if (cmd.getCommand().equalsIgnoreCase("ADDDOWNLOAD")) {
            String filename = cmd.getKey("file");
            String hash = cmd.getKey("hash");
            long size = -1;

            try {
                size = Long.parseLong(cmd.getKey("size"));
            } catch (Exception e) {
            }

            long transmit = -1;

            try {
                transmit = Long.parseLong(cmd.getKey("transmit"));
            } catch (Exception e) {
            }

            String state = cmd.getKey("state");

            DownloadContainer dc = new DownloadContainer(filename, hash, size,
                    transmit, state);
            addEventListener(dc);
            downloads.put(cmd.getCommandArgument(), dc);
            downloads.put(dc, cmd.getCommandArgument());
            DownloadQueue.getInstance().add(dc);

            //fireEvent(new DownloadAddedEvent(dc));
        } else if (cmd.getCommand().equalsIgnoreCase("CHGDOWNLOAD")) {
            String filename = cmd.getKey("file");
            String hash = cmd.getKey("hash");
            long size = -1;

            try {
                size = Long.parseLong(cmd.getKey("size"));
            } catch (Exception e) {
            }

            long transmit = -1;

            try {
                transmit = Long.parseLong(cmd.getKey("transmit"));
            } catch (Exception e) {
            }

            long elapsed = -1;

            try {
                elapsed = Long.parseLong(cmd.getKey("elapsed"));
            } catch (Exception e) {
            }

            long throughput = -1;

            try {
                throughput = Long.parseLong(cmd.getKey("throughput"));
            } catch (Exception e) {
            }

            String state = cmd.getKey("state");
            DownloadContainer dc = (DownloadContainer) downloads.get(cmd.getCommandArgument());

            if (dc != null) {
                DownloadUpdatedEvent due = new DownloadUpdatedEvent(dc);
                due.setElapsed(elapsed);
                due.setFilename(filename);
                due.setHash(hash);
                due.setSize(size);
                due.setState(state);
                due.setThroughput(throughput);
                due.setTransmit(transmit);

                // fire event directly
                dc.downloadUpdated(due);
            }
        }
    }

  /*
   * Controles which Event raises which Listener.
   *
   * Search & Download events are handled directly by DispatchCommand()
   *
   *
   */
    private synchronized void fireEvent(Event evt)
    {
        for (int i = 0; i < listeners.size(); i++) {
            EventListener listener = (EventListener) listeners.get(i);

            // debug event
            if (evt instanceof DebugEvent &&
                    listener instanceof DebugEventListener) {
                if (((DebugEvent) evt).getType() == DebugEvent.SEND) {
                    ((DebugEventListener) listener).commandSent((DebugEvent) evt);
                } else {
                    ((DebugEventListener) listener).commandReceived((DebugEvent) evt);
                }
            } else if (listener instanceof SharesEventListener) {
                // shares events
                if (evt instanceof SharesControlEvent) {
                    if (((SharesControlEvent) evt).getAction() == ControlEvent.STARTED) {
                        ((SharesEventListener) listener).sharesListingStarted((SharesControlEvent) evt);
                    } else if (((SharesControlEvent) evt).getAction() == ControlEvent.FINISHED) {
                        ((SharesEventListener) listener).sharesListingFinished((SharesControlEvent) evt);
                    } else if (((SharesControlEvent) evt).getAction() == SharesControlEvent.SYNC_STARTED) {
                        ((SharesEventListener) listener).sharesSyncStarted((SharesControlEvent) evt);
                    } else if (((SharesControlEvent) evt).getAction() == SharesControlEvent.SYNC_STATUS) {
                        ((SharesEventListener) listener).sharesSyncStatus((SharesControlEvent) evt);
                    } else if (((SharesControlEvent) evt).getAction() == SharesControlEvent.SYNC_FINISHED) {
                        ((SharesEventListener) listener).sharesSyncFinished((SharesControlEvent) evt);
                    }
                } else if (evt instanceof ShareItemEvent) {
                    ((SharesEventListener) listener).shareItemReceived((ShareItemEvent) evt);
                }
            } else if (listener instanceof NetworkEventListener) {
                // stats and network events
                if (evt instanceof OnlineEvent) {
                    ((NetworkEventListener) listener).attached((OnlineEvent) evt);
                }

                if (evt instanceof OfflineEvent) {
                    ((NetworkEventListener) listener).detached((OfflineEvent) evt);
                }

                if (evt instanceof StatsEvent) {
                    ((NetworkEventListener) listener).statsUpdate((StatsEvent) evt);
                }
            } else if (listener instanceof ErrorEventListener) {
                // errors
                ((ErrorEventListener) listener).onError((ErrorEvent) evt);
            }
             /*else if (listener instanceof DownloadEventListener) {
                  if (evt instanceof DownloadAddedEvent) {
                          System.out.println("add");
                                 //((DownloadEventListener)listener).downloadAdded((DownloadAddedEvent)evt);
                  }
                  // DownloadUpdatedEvent gets fired directly in dispatchCommand()
                  if (evt instanceof DownloadUpdatedEvent) {
                          // notify only the concerning dc
                          if (listener == ((DownloadUpdatedEvent)evt).getDownloadContainer()) {
                                  ((DownloadEventListener)listener).downloadUpdated((DownloadUpdatedEvent)evt);
                          }
                  }
            }*/
        }
    }

    private void process()
    {
        OutputStream out;
        InputStream in;
        StreamLexer lexer;

        try {
            if (socket == null) {
                socket = new Socket(host, port);
            } else { // FIX: if (!socket.isConnected()) {
                socket = new Socket(host, port);
            }

            connectState = CONNECTING;
        } catch (IOException e) {
            connectState = OFFLINE;
            fireEvent(new ErrorEvent("giFT daemon not running", e));
            fireEvent(new OfflineEvent());

            return;
        }

        try {
            out = socket.getOutputStream();
            in = socket.getInputStream();
            lexer = new StreamLexer(in);

            Command cmd = new Command("attach");
            cmd.addKey("client", "XNap");
            cmd.addKey("version", XNap.VERSION);

            if (user != null) {
                cmd.addKey("profile", user);
            }

            queueCommand(cmd);
            cmd = null;

            while (!exitProcessThread) {
                Thread.sleep(10);

                if (false) { // FIX : !socket.isConnected()

                    break;
                }

                if (in.available() != 0) {
                    cmd = lexer.parse();

                    if (debug) {
                        fireEvent(new DebugEvent(DebugEvent.RECEIVE, cmd));
                    }

                    dispatchCommand(cmd);
                }

                cmd = null;

                if (!outQueue.isEmpty()) {
                    cmd = (Command) outQueue.remove(0);

                    if (debug) {
                        fireEvent(new DebugEvent(DebugEvent.SEND, cmd));
                    }

                    ;
                    out.write(cmd.print().getBytes());
                }

                if (System.currentTimeMillis() > NetworkStatsTimer) {
                    UpdateNetworkStats();
                    NetworkStatsTimer = System.currentTimeMillis() +
                        NETWORK_STATS_INTERVAL;
                }
            }
        } catch (Exception e) {
            fireEvent(new ErrorEvent("processing error", e));
        } finally {
            try {
                if (socket != null) {
                    socket.close();
                }
        socket = null;
                if (connectState == ONLINE) {
                    connectState = OFFLINE;
                    fireEvent(new OfflineEvent());
                }
            } catch (IOException e) {
                fireEvent(new ErrorEvent(e));
            }
        }
    }

    private void queueCommand(Command cmd)
    {
        outQueue.add(cmd);
    }
}
TOP

Related Classes of xnap.plugin.gift.net.Engine

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.