package edu.washington.cs.oneswarm.f2f; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.net.URL; import java.util.Timer; import java.util.TimerTask; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.config.ParameterListener; import org.gudy.azureus2.core3.disk.DiskManagerFileInfo; import org.gudy.azureus2.core3.download.DownloadManager; import org.gudy.azureus2.core3.download.DownloadManagerListener; import org.gudy.azureus2.core3.download.DownloadManagerStats; import org.gudy.azureus2.core3.global.GlobalManagerDownloadRemovalVetoException; import org.gudy.azureus2.core3.peer.PEPeer; import org.gudy.azureus2.core3.peer.PEPeerManager; import org.gudy.azureus2.core3.peer.PEPeerManagerListener; import org.gudy.azureus2.core3.tracker.client.TRTrackerAnnouncer; import org.gudy.azureus2.core3.tracker.client.TRTrackerAnnouncerListener; import org.gudy.azureus2.core3.tracker.client.TRTrackerAnnouncerResponse; import com.aelitis.azureus.core.AzureusCore; import com.aelitis.azureus.core.AzureusCoreComponent; import com.aelitis.azureus.core.AzureusCoreException; import com.aelitis.azureus.core.AzureusCoreFactory; import com.aelitis.azureus.core.AzureusCoreLifecycleListener; import com.aelitis.azureus.core.impl.AzureusCoreImpl; class CLI_Main { AzureusCore mCore; static CLI_Main mInst = null; public static CLI_Main get() { return mInst; } File mErr = null, mOut = null; public File getOut() { return mOut; } public File getErr() { return mErr; } public CLI_Main(String[] args) { try { mErr = File.createTempFile("ost", "err"); mOut = File.createTempFile("ost", "out"); // skip this for now. // System.out.println("tail -f " + mOut.getAbsolutePath()); // System.out.println("tail -f " + mErr.getAbsolutePath()); // // System.setOut(new PrintStream( new FileOutputStream(mOut), true // )); // System.setErr(new PrintStream( new FileOutputStream(mErr), true // )); } catch (IOException e) { System.err.println("Couldn't redirect stdout, err. " + e); e.printStackTrace(); System.exit(-1); } // this makes sure we're the only instance running on this machine. // DEBUG -- removed for local testing // (new Thread(new ReceiveOrders(4312))).start(); // final SendStatus status = new SendStatus("recycle.cs.washington.edu", // 4312); final String[] args_shadow = args; byte[] torrent_bytes = null; boolean keep_last = false, keep_curr = false; int rate = 1024; // 1 MBps int wait_after_finished_secs = 0; // default is immediately quit double wait_after_ratio = Double.MAX_VALUE; String outfile = null; // COConfigurationManager.setParameter("dht.logging", false); try { for (int i = 0; i < args.length; i++) { if (args[i].equals("-file")) { FileInputStream fis = new FileInputStream(args[++i]); torrent_bytes = new byte[fis.available()]; fis.read(torrent_bytes); } else if (args[i].equals("-bytes")) { torrent_bytes = args[++i].getBytes(); } else if (args[i].equals("-keep_last")) { keep_last = true; } else if (args[i].equals("-keep_curr")) { keep_curr = true; } else if (args[i].equals("-outfile")) { outfile = args[++i]; } else if (args[i].equals("-rate")) { rate = Integer.parseInt(args[++i]); } else if (args[i].equals("-stay")) { wait_after_finished_secs = Integer.parseInt(args[++i]); } else if (args[i].equals("-ratio")) { wait_after_ratio = Double.parseDouble(args[++i]); } } } catch (IOException e) { System.err.println("Couldn't load torrent: " + e); System.exit(-1); } COConfigurationManager.preInitialise(); impose_settings(rate); long start = System.currentTimeMillis(); mCore = AzureusCoreFactory.create(); System.out.println("starting core took: " + (System.currentTimeMillis() - start) + " ms"); final Object ready = new Object(); mCore.addLifecycleListener(new AzureusCoreLifecycleListener() { public void componentCreated(AzureusCore core, AzureusCoreComponent component) { System.out.println("component created: " + component); } public boolean requiresPluginInitCompleteBeforeStartedEvent() { return false; } public boolean restartRequested(AzureusCore core) throws AzureusCoreException { return false; } public void started(AzureusCore core) { System.out.println("Core started"); // DEBUG -- removed for local testing // (new Thread(status)).start(); synchronized (ready) { ready.notifyAll(); } } public boolean stopRequested(AzureusCore core) throws AzureusCoreException { return false; } public void stopped(AzureusCore core) { } public void stopping(AzureusCore core) { } public boolean syncInvokeRequired() { return false; } }); mCore.start(); try { synchronized (ready) { while (mCore.isStarted() == false) ready.wait(); } } catch (Exception e) { System.err.println(e); e.printStackTrace(); System.exit(-1); } // Remove all existing download managers if they exist. for (DownloadManager dm : (DownloadManager[]) (mCore.getGlobalManager() .getDownloadManagers().toArray(new DownloadManager[0]))) { if (keep_last == false) { System.out.println("Removing existing download manager: " + dm); try { mCore.getGlobalManager().removeDownloadManager(dm); } catch (AzureusCoreException e) { e.printStackTrace(); } catch (GlobalManagerDownloadRemovalVetoException e) { e.printStackTrace(); } } /** * If there is some weirdness during torrent add (or out of program * movement of torrent / data files), Azureus will simply fail * silently during DownloadManager recreation. Here we try to detect * when things are weird. */ dm.addListener(new DownloadManagerListener() { public void completionChanged(DownloadManager manager, boolean completed) { } public void downloadComplete(DownloadManager manager) { } public void filePriorityChanged(DownloadManager download, DiskManagerFileInfo file) { } public void positionChanged(DownloadManager download, int oldPosition, int newPosition) { } public void stateChanged(DownloadManager manager, int state) { System.out.println(manager + " state: " + state); if (state == DownloadManager.STATE_ERROR) { try { mCore.getGlobalManager().removeDownloadManager(manager); } catch (AzureusCoreException e) { e.printStackTrace(); } catch (GlobalManagerDownloadRemovalVetoException e) { e.printStackTrace(); } } } }); } // make sure we have this in the CP.. // LocalIdentity.get(); if (torrent_bytes != null) start_distribution(torrent_bytes, keep_curr, outfile, wait_after_finished_secs, wait_after_ratio); else { System.out.println("Nothing to do explicitly..."); try { // DEBUG -- removed for local testing // while( status.getTorrent() == null ) // Thread.sleep(1000); // DEBUG -- removed for local testing // System.out.println( // "got torrent bytes from coordinator, starting..."); // start_distribution(torrent_bytes); } catch (Exception e) { System.err.println(e); e.printStackTrace(); } } } /** * @param args */ public static void main(String[] args) { mInst = new CLI_Main(args); } private static void start_distribution(byte[] torrent_bytes, boolean keep_curr, String outfile, final int wait_after_finished_secs, final double wait_after_ratio) { try { File torrent = File.createTempFile("ost", "torrent"); FileOutputStream fos = new FileOutputStream(torrent); fos.write(torrent_bytes); fos.close(); if (keep_curr) torrent.deleteOnExit(); File saved = null; if (outfile == null) { saved = File.createTempFile("ost", "file"); if (keep_curr) saved.deleteOnExit(); } else { saved = new File(outfile); } final DownloadManager dm = AzureusCoreFactory.getSingleton().getGlobalManager() .addDownloadManager(torrent.getAbsolutePath(), saved.getAbsolutePath()); dm.addListener(new DownloadManagerListener() { long dist_start_time = System.currentTimeMillis(); public void completionChanged(DownloadManager manager, boolean completed) { } public void downloadComplete(DownloadManager manager) { System.out.println("dl_completion " + (System.currentTimeMillis() - dist_start_time) / 1000); System.out.println("download completed. waiting: " + wait_after_finished_secs + " / ratio: " + wait_after_ratio); final long completion_time = System.currentTimeMillis(); (new Timer()).schedule(new TimerTask() { public void run() { DownloadManagerStats stats = dm.getStats(); double ratio = (double) stats.getTotalDataBytesSent() / (double) stats.getTotalDataBytesReceived(); if (ratio > wait_after_ratio) { System.out.println("ratio reached: " + ratio); exit(); } if ((System.currentTimeMillis() - completion_time) > wait_after_finished_secs * 1000) { System.out.println("wait after time reached: " + wait_after_finished_secs); exit(); } } }, 1000, 1000); } public void filePriorityChanged(DownloadManager download, DiskManagerFileInfo file) { } public void positionChanged(DownloadManager download, int oldPosition, int newPosition) { } public void stateChanged(final DownloadManager manager, int state) { System.out.println("State changed for: " + manager.getTorrentFileName() + " -- " + state); if (state == DownloadManager.STATE_DOWNLOADING) { System.out.println("download manager initialized, adding listeners..."); manager.getPeerManager().addListener(new PEPeerManagerListener() { public void destroyed() { } public void peerAdded(PEPeerManager manager, PEPeer peer) { System.out.println("got peer: " + peer); } public void peerRemoved(PEPeerManager manager, PEPeer peer) { } }); manager.getTrackerClient().addListener(new TRTrackerAnnouncerListener() { public void receivedTrackerResponse(TRTrackerAnnouncerResponse response) { System.out.println("Received tracker response: " + response.getStatus() + " peers: " + response.getPeers().length); dist_start_time = System.currentTimeMillis(); } public void urlChanged(TRTrackerAnnouncer announcer, URL old_url, URL new_url, boolean explicit) { } public void urlRefresh() { } }); (new Timer("Download status reporter", true)).schedule(new TimerTask() { public void run() { DownloadManagerStats stats = manager.getStats(); System.out.println(" DL: " + stats.getDataReceiveRate() / 1024 + " [" + stats.getTotalDataBytesReceived() / (1024) + "]" + " UL: " + stats.getDataSendRate() / 1024 + " [" + stats.getTotalDataBytesSent() / (1024) + "]" + " Peers: " + manager.getPeerManager().getPeers().size() + " %: " + (double) ((double) stats.getTotalGoodDataBytesReceived() / (double) manager .getSize()) * 100.0 + " MaxUL: " + COConfigurationManager .getIntParameter("Max Upload Speed KBs")); } }, 1000, 5 * 1000); } } }); } catch (Exception e) { System.err.println("Error downloading specified swarm: " + e); e.printStackTrace(); } } private static void impose_settings(int rate) { COConfigurationManager.setParameter("Save Torrent Files", false); COConfigurationManager.setParameter("Max Upload Speed KBs", rate); System.out.println("rate is: " + rate); COConfigurationManager.setParameter("LAN Speed Enabled", false); System.out.println("default torrent dir is: " + COConfigurationManager.getStringParameter("General_sDefaultTorrent_Directory")); COConfigurationManager.addParameterListener("General_sDefaultTorrent_Directory", new ParameterListener() { public void parameterChanged(String parameterName) { System.out.println("changed********: " + parameterName); System.out.println("default torrent dir is: " + COConfigurationManager .getStringParameter("General_sDefaultTorrent_Directory")); } }); } public static void exit() { try { if (AzureusCoreImpl.isCoreAvailable()) { System.out.println("Calling core stop"); AzureusCoreImpl.getSingleton().stop(); } } catch (Exception e) { System.err.println("stop exception: " + e); e.printStackTrace(); System.exit(0); } } }