Search in sources :

Example 1 with DownloadManagerListener

use of com.biglybt.pif.download.DownloadManagerListener in project BiglyBT by BiglySoftware.

the class BuddyPluginBeta method startup.

protected void startup() {
    plugin_interface.addEventListener(new PluginEventListener() {

        @Override
        public void handleEvent(PluginEvent ev) {
            int type = ev.getType();
            if (type == PluginEvent.PEV_PLUGIN_OPERATIONAL) {
                pluginAdded((PluginInterface) ev.getValue());
            } else if (type == PluginEvent.PEV_PLUGIN_NOT_OPERATIONAL) {
                pluginRemoved((PluginInterface) ev.getValue());
            }
        }
    });
    PluginInterface[] plugins = plugin_interface.getPluginManager().getPlugins(true);
    for (PluginInterface pi : plugins) {
        if (pi.getPluginState().isOperational()) {
            pluginAdded(pi);
        }
    }
    boolean check_all = COConfigurationManager.getBooleanParameter("azbuddy.dchat.autotracker.scan", true);
    COConfigurationManager.setParameter("azbuddy.dchat.autotracker.scan", false);
    plugin_interface.getDownloadManager().addListener(new DownloadManagerListener() {

        private Set<String> checked = new HashSet<>();

        @Override
        public void downloadAdded(Download download) {
            if (COConfigurationManager.getBooleanParameter(ConfigKeys.Tag.BCFG_TRACKER_AUTO_TAG_INTERESTING_TRACKERS)) {
                Torrent torrent = download.getTorrent();
                if (torrent != null) {
                    TOTorrent to_torrent = PluginCoreUtils.unwrap(download.getTorrent());
                    if (TorrentUtils.isReallyPrivate(to_torrent)) {
                        Set<String> hosts = TorrentUtils.getUniqueTrackerHosts(to_torrent);
                        if (hosts.size() == 1) {
                            String tracker = DNSUtils.getInterestingHostSuffix(hosts.iterator().next());
                            if (tracker != null && !checked.contains(tracker)) {
                                checked.add(tracker);
                                try {
                                    String config_key = "azbuddy.dchat.autotracker.host." + Base32.encode(tracker.getBytes("UTF-8"));
                                    boolean done = COConfigurationManager.getBooleanParameter(config_key, false);
                                    if (!done) {
                                        COConfigurationManager.setParameter(config_key, true);
                                        String chat_key = "Tracker: " + tracker;
                                        ChatInstance chat = getChat(AENetworkClassifier.AT_PUBLIC, chat_key);
                                        chat.setFavourite(true);
                                        BuddyPluginUI.openChat(chat);
                                        TagManager tm = TagManagerFactory.getTagManager();
                                        if (tm.isEnabled()) {
                                            TagType tt = tm.getTagType(TagType.TT_DOWNLOAD_MANUAL);
                                            Tag tag = tt.getTag(tracker, true);
                                            if (tag == null) {
                                                tag = tt.createTag(tracker, false);
                                                tag.setPublic(false);
                                                tt.addTag(tag);
                                                TagFeatureProperties tfp = (TagFeatureProperties) tag;
                                                TagProperty tp = tfp.getProperty(TagFeatureProperties.PR_TRACKERS);
                                                tp.setStringList(new String[] { tracker });
                                            }
                                        }
                                    }
                                } catch (Throwable e) {
                                }
                            }
                        }
                    }
                }
            }
        }

        @Override
        public void downloadRemoved(Download download) {
        }
    }, check_all);
}
Also used : DownloadManagerListener(com.biglybt.pif.download.DownloadManagerListener) TagProperty(com.biglybt.core.tag.TagFeatureProperties.TagProperty) Torrent(com.biglybt.pif.torrent.Torrent) TOTorrent(com.biglybt.core.torrent.TOTorrent) PluginEventListener(com.biglybt.pif.PluginEventListener) PluginInterface(com.biglybt.pif.PluginInterface) TagType(com.biglybt.core.tag.TagType) TagManager(com.biglybt.core.tag.TagManager) TOTorrent(com.biglybt.core.torrent.TOTorrent) Tag(com.biglybt.core.tag.Tag) TagFeatureProperties(com.biglybt.core.tag.TagFeatureProperties) PluginEvent(com.biglybt.pif.PluginEvent) Download(com.biglybt.pif.download.Download)

Example 2 with DownloadManagerListener

use of com.biglybt.pif.download.DownloadManagerListener in project BiglyBT by BiglySoftware.

the class MagnetPluginMDDownloader method startSupport.

private void startSupport(final DownloadListener listener) {
    String hash_str = ByteFormatter.encodeString(hash);
    File tmp_dir = null;
    File data_file = null;
    File torrent_file = null;
    DownloadManager download_manager = plugin_interface.getDownloadManager();
    Download download = null;
    final Throwable[] error = { null };
    final boolean[] manually_removed = { false };
    final ByteArrayOutputStream result = new ByteArrayOutputStream(32 * 1024);
    TOTorrentAnnounceURLSet[] url_sets = null;
    try {
        synchronized (active_set) {
            if (active_set.contains(hash_str)) {
                throw (new Exception("Download already active for hash " + hash_str));
            }
            active_set.add(hash_str);
        }
        Download existing_download = download_manager.getDownload(hash);
        if (existing_download != null) {
            throw (new Exception("download already exists"));
        }
        tmp_dir = AETemporaryFileHandler.createTempDir();
        int rand = RandomUtils.generateRandomIntUpto(10000);
        data_file = new File(tmp_dir, hash_str + "_" + rand + ".torrent");
        torrent_file = new File(tmp_dir, hash_str + "_" + rand + ".metatorrent");
        RandomAccessFile raf = new RandomAccessFile(data_file, "rw");
        try {
            byte[] buffer = new byte[512 * 1024];
            Arrays.fill(buffer, (byte) 0xff);
            for (long i = 0; i < 64 * 1024 * 1024; i += buffer.length) {
                raf.write(buffer);
            }
        } finally {
            raf.close();
        }
        URL announce_url = TorrentUtils.getDecentralisedURL(hash);
        TOTorrentCreator creator = TOTorrentFactory.createFromFileOrDirWithFixedPieceLength(data_file, announce_url, 16 * 1024);
        TOTorrent meta_torrent = creator.create();
        String[] bits = args.split("&");
        List<String> trackers = new ArrayList<>();
        String name = "magnet:" + Base32.encode(hash);
        Map<String, String> magnet_args = new HashMap<>();
        for (String bit : bits) {
            String[] x = bit.split("=");
            if (x.length == 2) {
                String lhs = x[0].toLowerCase();
                String rhs = UrlUtils.decode(x[1]);
                magnet_args.put(lhs, rhs);
                if (lhs.equals("tr")) {
                    String tracker = rhs;
                    trackers.add(tracker);
                } else if (lhs.equals("dn")) {
                    name = rhs;
                }
            }
        }
        if (trackers.size() > 0) {
            // stick the decentralised one we created above in position 0 - this will be
            // removed later if the torrent is downloaded
            trackers.add(0, announce_url.toExternalForm());
            TOTorrentAnnounceURLGroup ag = meta_torrent.getAnnounceURLGroup();
            List<TOTorrentAnnounceURLSet> sets = new ArrayList<>();
            for (String tracker : trackers) {
                try {
                    URL tracker_url = new URL(tracker);
                    sets.add(ag.createAnnounceURLSet(new URL[] { tracker_url }));
                } catch (Throwable e) {
                    Debug.out(e);
                }
            }
            if (sets.size() > 0) {
                url_sets = sets.toArray(new TOTorrentAnnounceURLSet[sets.size()]);
                ag.setAnnounceURLSets(url_sets);
            }
        }
        if (!data_file.delete()) {
            throw (new Exception("Failed to delete " + data_file));
        }
        meta_torrent.setHashOverride(hash);
        TorrentUtils.setFlag(meta_torrent, TorrentUtils.TORRENT_FLAG_METADATA_TORRENT, true);
        TorrentUtils.setFlag(meta_torrent, TorrentUtils.TORRENT_FLAG_LOW_NOISE, true);
        meta_torrent.serialiseToBEncodedFile(torrent_file);
        download_manager.clearNonPersistentDownloadState(hash);
        download = download_manager.addNonPersistentDownloadStopped(PluginCoreUtils.wrap(meta_torrent), torrent_file, data_file);
        String display_name = MessageText.getString("MagnetPlugin.use.md.download.name", new String[] { name });
        DownloadManagerState state = PluginCoreUtils.unwrap(download).getDownloadState();
        state.setDisplayName(display_name + ".torrent");
        if (networks.size() == 0 || (networks.size() == 1 && networks.contains(AENetworkClassifier.AT_PUBLIC))) {
            for (String network : AENetworkClassifier.AT_NETWORKS) {
                state.setNetworkEnabled(network, true);
            }
        } else {
            for (String network : networks) {
                state.setNetworkEnabled(network, true);
            }
            if (!networks.contains(AENetworkClassifier.AT_PUBLIC)) {
                state.setNetworkEnabled(AENetworkClassifier.AT_PUBLIC, false);
            }
        }
        if (!plugin.isNetworkEnabled(AENetworkClassifier.AT_PUBLIC)) {
            state.setNetworkEnabled(AENetworkClassifier.AT_PUBLIC, false);
        }
        final List<InetSocketAddress> peers_to_inject = new ArrayList<>();
        if (addresses != null && addresses.length > 0) {
            String[] enabled_nets = state.getNetworks();
            for (InetSocketAddress address : addresses) {
                String host = AddressUtils.getHostAddress(address);
                String net = AENetworkClassifier.categoriseAddress(host);
                for (String n : enabled_nets) {
                    if (n == net) {
                        peers_to_inject.add(address);
                        break;
                    }
                }
            }
        }
        final Set<String> peer_networks = new HashSet<>();
        final List<Map<String, Object>> peers_for_cache = new ArrayList<>();
        download.addPeerListener(new DownloadPeerListener() {

            @Override
            public void peerManagerAdded(final Download download, final PeerManager peer_manager) {
                if (cancelled || completed) {
                    download.removePeerListener(this);
                    return;
                }
                final PEPeerManager pm = PluginCoreUtils.unwrap(peer_manager);
                peer_manager.addListener(new PeerManagerListener2() {

                    private PeerManagerListener2 pm_listener = this;

                    private int md_size;

                    @Override
                    public void eventOccurred(PeerManagerEvent event) {
                        if (cancelled || completed) {
                            peer_manager.removeListener(this);
                            return;
                        }
                        if (event.getType() != PeerManagerEvent.ET_PEER_ADDED) {
                            return;
                        }
                        final Peer peer = event.getPeer();
                        try {
                            String peer_ip = peer.getIp();
                            String network = AENetworkClassifier.categoriseAddress(peer_ip);
                            synchronized (peer_networks) {
                                peer_networks.add(network);
                                Map<String, Object> map = new HashMap<>();
                                peers_for_cache.add(map);
                                map.put("ip", peer_ip.getBytes("UTF-8"));
                                map.put("port", new Long(peer.getPort()));
                            }
                        } catch (Throwable e) {
                            Debug.out(e);
                        }
                        peer.addListener(new PeerListener2() {

                            @Override
                            public void eventOccurred(PeerEvent event) {
                                if (cancelled || completed || md_size > 0) {
                                    peer.removeListener(this);
                                    return;
                                }
                                if (event.getType() != PeerEvent.ET_STATE_CHANGED) {
                                    return;
                                }
                                if ((Integer) event.getData() != Peer.TRANSFERING) {
                                    return;
                                }
                                synchronized (pm_listener) {
                                    if (md_size > 0) {
                                        return;
                                    }
                                    md_size = pm.getTorrentInfoDictSize();
                                    if (md_size > 0) {
                                        peer_manager.removeListener(pm_listener);
                                    } else {
                                        return;
                                    }
                                }
                                listener.reportProgress(0, md_size);
                                new AEThread2("") {

                                    @Override
                                    public void run() {
                                        DiskManagerChannel channel = null;
                                        try {
                                            channel = download.getDiskManagerFileInfo()[0].createChannel();
                                            final DiskManagerRequest request = channel.createRequest();
                                            request.setType(DiskManagerRequest.REQUEST_READ);
                                            request.setOffset(0);
                                            request.setLength(md_size);
                                            request.setMaximumReadChunkSize(16 * 1024);
                                            request.addListener(new DiskManagerListener() {

                                                @Override
                                                public void eventOccurred(DiskManagerEvent event) {
                                                    int type = event.getType();
                                                    if (type == DiskManagerEvent.EVENT_TYPE_FAILED) {
                                                        error[0] = event.getFailure();
                                                        running_sem.releaseForever();
                                                    } else if (type == DiskManagerEvent.EVENT_TYPE_SUCCESS) {
                                                        PooledByteBuffer buffer = null;
                                                        try {
                                                            buffer = event.getBuffer();
                                                            byte[] bytes = buffer.toByteArray();
                                                            int dl_size;
                                                            synchronized (MagnetPluginMDDownloader.this) {
                                                                result.write(bytes);
                                                                dl_size = result.size();
                                                                if (dl_size == md_size) {
                                                                    completed = true;
                                                                    listener.reportProgress(md_size, md_size);
                                                                    running_sem.releaseForever();
                                                                }
                                                            }
                                                            if (!completed) {
                                                                listener.reportProgress(dl_size, md_size);
                                                            }
                                                        } catch (Throwable e) {
                                                            error[0] = e;
                                                            request.cancel();
                                                            running_sem.releaseForever();
                                                        } finally {
                                                            if (buffer != null) {
                                                                buffer.returnToPool();
                                                            }
                                                        }
                                                    } else if (type == DiskManagerEvent.EVENT_TYPE_BLOCKED) {
                                                    // System.out.println( "Waiting..." );
                                                    }
                                                }
                                            });
                                            synchronized (MagnetPluginMDDownloader.this) {
                                                if (cancelled) {
                                                    return;
                                                }
                                                requests.add(request);
                                            }
                                            request.run();
                                            synchronized (MagnetPluginMDDownloader.this) {
                                                requests.remove(request);
                                            }
                                        } catch (Throwable e) {
                                            error[0] = e;
                                            running_sem.releaseForever();
                                        } finally {
                                            if (channel != null) {
                                                channel.destroy();
                                            }
                                        }
                                    }
                                }.start();
                            }
                        });
                    }
                });
            }

            @Override
            public void peerManagerRemoved(Download download, PeerManager peer_manager) {
            }
        });
        final Download f_download = download;
        DownloadManagerListener dl_listener = new DownloadManagerListener() {

            private Object lock = this;

            private TimerEventPeriodic timer_event;

            private boolean removed;

            @Override
            public void downloadAdded(final Download download) {
                if (download == f_download) {
                    synchronized (lock) {
                        if (!removed) {
                            if (timer_event == null) {
                                timer_event = SimpleTimer.addPeriodicEvent("announcer", 30 * 1000, new TimerEventPerformer() {

                                    @Override
                                    public void perform(TimerEvent event) {
                                        synchronized (lock) {
                                            if (removed) {
                                                return;
                                            }
                                            if (running_sem.isReleasedForever()) {
                                                if (timer_event != null) {
                                                    timer_event.cancel();
                                                    timer_event = null;
                                                }
                                                return;
                                            }
                                        }
                                        download.requestTrackerAnnounce(true);
                                        injectPeers(download);
                                    }
                                });
                            }
                            if (peers_to_inject.size() > 0) {
                                SimpleTimer.addEvent("injecter", SystemTime.getOffsetTime(5 * 1000), new TimerEventPerformer() {

                                    @Override
                                    public void perform(TimerEvent event) {
                                        injectPeers(download);
                                    }
                                });
                            }
                        }
                    }
                }
            }

            private void injectPeers(Download download) {
                PeerManager pm = download.getPeerManager();
                if (pm != null) {
                    for (InetSocketAddress address : peers_to_inject) {
                        pm.addPeer(AddressUtils.getHostAddress(address), address.getPort());
                    }
                }
            }

            @Override
            public void downloadRemoved(Download dl) {
                if (dl == f_download) {
                    synchronized (lock) {
                        removed = true;
                        if (timer_event != null) {
                            timer_event.cancel();
                            timer_event = null;
                        }
                    }
                    if (!(cancelled || completed)) {
                        error[0] = new Exception("Download manually removed");
                        manually_removed[0] = true;
                        running_sem.releaseForever();
                    }
                }
            }
        };
        download_manager.addListener(dl_listener, true);
        try {
            download.moveTo(1);
            download.setForceStart(true);
            download.setFlag(Download.FLAG_DISABLE_AUTO_FILE_MOVE, true);
            running_sem.reserve();
        } finally {
            download_manager.removeListener(dl_listener);
        }
        if (completed) {
            byte[] bytes = result.toByteArray();
            Map info = BDecoder.decode(bytes);
            Map map = new HashMap();
            map.put("info", info);
            TOTorrent torrent = TOTorrentFactory.deserialiseFromMap(map);
            byte[] final_hash = torrent.getHash();
            if (!Arrays.equals(hash, final_hash)) {
                throw (new Exception("Metadata torrent hash mismatch: expected=" + ByteFormatter.encodeString(hash) + ", actual=" + ByteFormatter.encodeString(final_hash)));
            }
            if (url_sets != null) {
                // first entry should be the decentralised one that we want to remove now
                List<TOTorrentAnnounceURLSet> updated = new ArrayList<>();
                for (TOTorrentAnnounceURLSet set : url_sets) {
                    if (!TorrentUtils.isDecentralised(set.getAnnounceURLs()[0])) {
                        updated.add(set);
                    }
                }
                if (updated.size() == 0) {
                    url_sets = null;
                } else {
                    url_sets = updated.toArray(new TOTorrentAnnounceURLSet[updated.size()]);
                }
            }
            if (url_sets != null) {
                torrent.setAnnounceURL(url_sets[0].getAnnounceURLs()[0]);
                torrent.getAnnounceURLGroup().setAnnounceURLSets(url_sets);
            } else {
                torrent.setAnnounceURL(TorrentUtils.getDecentralisedURL(hash));
            }
            if (peers_for_cache.size() > 0) {
                Map<String, List<Map<String, Object>>> peer_cache = new HashMap<>();
                peer_cache.put("tracker_peers", peers_for_cache);
                TorrentUtils.setPeerCache(torrent, peer_cache);
            }
            try {
                String dn = magnet_args.get("dn");
                if (dn != null) {
                    PlatformTorrentUtils.setContentTitle(torrent, dn);
                }
                String pfi_str = magnet_args.get("pfi");
                if (pfi_str != null) {
                    PlatformTorrentUtils.setContentPrimaryFileIndex(torrent, Integer.parseInt(pfi_str));
                }
            } catch (Throwable e) {
            }
            listener.complete(torrent, peer_networks);
        } else {
            if (cancelled) {
                throw (new Exception("Download cancelled"));
            } else {
                cancelSupport(true);
                try {
                    if (error[0] != null) {
                        throw (error[0]);
                    } else {
                        throw (new Exception("Download terminated prematurely"));
                    }
                } catch (Throwable e) {
                    listener.failed(manually_removed[0], e);
                    Debug.out(e);
                    throw (e);
                }
            }
        }
    } catch (Throwable e) {
        boolean was_cancelled = cancelled;
        cancelSupport(true);
        if (!was_cancelled) {
            listener.failed(manually_removed[0], e);
            Debug.out(e);
        }
    } finally {
        try {
            if (download != null) {
                try {
                    download.stop();
                } catch (Throwable e) {
                }
                try {
                    download.remove();
                } catch (Throwable e) {
                    Debug.out(e);
                }
            }
            List<DiskManagerRequest> to_cancel;
            synchronized (this) {
                to_cancel = new ArrayList<>(requests);
                requests.clear();
            }
            for (DiskManagerRequest request : to_cancel) {
                request.cancel();
            }
            if (torrent_file != null) {
                torrent_file.delete();
            }
            if (data_file != null) {
                data_file.delete();
            }
            if (tmp_dir != null) {
                tmp_dir.delete();
            }
        } catch (Throwable e) {
            Debug.out(e);
        } finally {
            synchronized (active_set) {
                active_set.remove(hash_str);
            }
            complete_sem.releaseForever();
        }
    }
}
Also used : InetSocketAddress(java.net.InetSocketAddress) DownloadManager(com.biglybt.pif.download.DownloadManager) DiskManagerListener(com.biglybt.pif.disk.DiskManagerListener) DiskManagerChannel(com.biglybt.pif.disk.DiskManagerChannel) DownloadPeerListener(com.biglybt.pif.download.DownloadPeerListener) RandomAccessFile(java.io.RandomAccessFile) PEPeerManager(com.biglybt.core.peer.PEPeerManager) RandomAccessFile(java.io.RandomAccessFile) File(java.io.File) DownloadManagerListener(com.biglybt.pif.download.DownloadManagerListener) DownloadManagerState(com.biglybt.core.download.DownloadManagerState) URL(java.net.URL) PooledByteBuffer(com.biglybt.pif.utils.PooledByteBuffer) Download(com.biglybt.pif.download.Download) DiskManagerRequest(com.biglybt.pif.disk.DiskManagerRequest) ByteArrayOutputStream(java.io.ByteArrayOutputStream) PEPeerManager(com.biglybt.core.peer.PEPeerManager) DiskManagerEvent(com.biglybt.pif.disk.DiskManagerEvent)

Aggregations

Download (com.biglybt.pif.download.Download)2 DownloadManagerListener (com.biglybt.pif.download.DownloadManagerListener)2 DownloadManagerState (com.biglybt.core.download.DownloadManagerState)1 PEPeerManager (com.biglybt.core.peer.PEPeerManager)1 Tag (com.biglybt.core.tag.Tag)1 TagFeatureProperties (com.biglybt.core.tag.TagFeatureProperties)1 TagProperty (com.biglybt.core.tag.TagFeatureProperties.TagProperty)1 TagManager (com.biglybt.core.tag.TagManager)1 TagType (com.biglybt.core.tag.TagType)1 TOTorrent (com.biglybt.core.torrent.TOTorrent)1 PluginEvent (com.biglybt.pif.PluginEvent)1 PluginEventListener (com.biglybt.pif.PluginEventListener)1 PluginInterface (com.biglybt.pif.PluginInterface)1 DiskManagerChannel (com.biglybt.pif.disk.DiskManagerChannel)1 DiskManagerEvent (com.biglybt.pif.disk.DiskManagerEvent)1 DiskManagerListener (com.biglybt.pif.disk.DiskManagerListener)1 DiskManagerRequest (com.biglybt.pif.disk.DiskManagerRequest)1 DownloadManager (com.biglybt.pif.download.DownloadManager)1 DownloadPeerListener (com.biglybt.pif.download.DownloadPeerListener)1 Torrent (com.biglybt.pif.torrent.Torrent)1