Search in sources :

Example 1 with MagnetURIHandlerException

use of com.biglybt.net.magneturi.MagnetURIHandlerException in project BiglyBT by BiglySoftware.

the class MagnetPlugin method initialize.

@Override
public void initialize(PluginInterface _plugin_interface) {
    plugin_interface = _plugin_interface;
    MagnetURIHandler uri_handler = MagnetURIHandler.getSingleton();
    final LocaleUtilities lu = plugin_interface.getUtilities().getLocaleUtilities();
    lu.addListener(new LocaleListener() {

        @Override
        public void localeChanged(Locale l) {
            updateLocale(lu);
        }
    });
    updateLocale(lu);
    BasicPluginConfigModel config = plugin_interface.getUIManager().createBasicPluginConfigModel(ConfigSection.SECTION_PLUGINS, PLUGIN_CONFIGSECTION_ID);
    config.addInfoParameter2("MagnetPlugin.current.port", String.valueOf(uri_handler.getPort()));
    secondary_lookup = config.addBooleanParameter2("MagnetPlugin.use.lookup.service", "MagnetPlugin.use.lookup.service", true);
    md_lookup = config.addBooleanParameter2("MagnetPlugin.use.md.download", "MagnetPlugin.use.md.download", true);
    md_lookup_delay = config.addIntParameter2("MagnetPlugin.use.md.download.delay", "MagnetPlugin.use.md.download.delay", MD_LOOKUP_DELAY_SECS_DEFAULT);
    md_lookup.addEnabledOnSelection(md_lookup_delay);
    timeout_param = config.addIntParameter2("MagnetPlugin.timeout.secs", "MagnetPlugin.timeout.secs", PLUGIN_DOWNLOAD_TIMEOUT_SECS_DEFAULT);
    sources_param = config.addStringListParameter2("MagnetPlugin.add.sources", "MagnetPlugin.add.sources", SOURCE_VALUES, SOURCE_STRINGS, SOURCE_VALUES[1]);
    sources_extra_param = config.addIntParameter2("MagnetPlugin.add.sources.extra", "MagnetPlugin.add.sources.extra", 0);
    magnet_recovery = config.addBooleanParameter2("MagnetPlugin.recover.magnets", "MagnetPlugin.recover.magnets", true);
    Parameter[] nps = new Parameter[AENetworkClassifier.AT_NETWORKS.length];
    for (int i = 0; i < nps.length; i++) {
        String nn = AENetworkClassifier.AT_NETWORKS[i];
        String config_name = "Network Selection Default." + nn;
        String msg_text = "ConfigView.section.connection.networks." + nn;
        final BooleanParameter param = config.addBooleanParameter2(config_name, msg_text, COConfigurationManager.getBooleanParameter(config_name));
        COConfigurationManager.addParameterListener(config_name, new com.biglybt.core.config.ParameterListener() {

            @Override
            public void parameterChanged(String name) {
                param.setDefaultValue(COConfigurationManager.getBooleanParameter(name));
            }
        });
        nps[i] = param;
        net_params.put(nn, param);
    }
    config.createGroup("label.default.nets", nps);
    MenuItemListener listener = new MenuItemListener() {

        @Override
        public void selected(MenuItem _menu, Object _target) {
            TableRow[] rows = (TableRow[]) _target;
            String cb_all_data = "";
            for (TableRow row : rows) {
                Torrent torrent;
                String name;
                Object ds = row.getDataSource();
                Download download = null;
                ShareResource share = null;
                if (ds instanceof ShareResourceFile) {
                    ShareResourceFile sf = (ShareResourceFile) ds;
                    try {
                        torrent = sf.getItem().getTorrent();
                    } catch (ShareException e) {
                        continue;
                    }
                    name = sf.getName();
                    share = sf;
                } else if (ds instanceof ShareResourceDir) {
                    ShareResourceDir sd = (ShareResourceDir) ds;
                    try {
                        torrent = sd.getItem().getTorrent();
                    } catch (ShareException e) {
                        continue;
                    }
                    name = sd.getName();
                    share = sd;
                } else if (ds instanceof Download) {
                    download = (Download) ds;
                    torrent = download.getTorrent();
                    name = download.getName();
                } else {
                    continue;
                }
                boolean is_share = false;
                Set<String> networks = new HashSet<>();
                if (share != null) {
                    is_share = true;
                    Map<String, String> properties = share.getProperties();
                    if (properties != null) {
                        String nets = properties.get(ShareManager.PR_NETWORKS);
                        if (nets != null) {
                            String[] bits = nets.split(",");
                            for (String bit : bits) {
                                bit = AENetworkClassifier.internalise(bit.trim());
                                if (bit != null) {
                                    networks.add(bit);
                                }
                            }
                        }
                    }
                }
                if (download != null) {
                    TorrentAttribute ta = plugin_interface.getTorrentManager().getAttribute(TorrentAttribute.TA_NETWORKS);
                    String[] nets = download.getListAttribute(ta);
                    networks.addAll(Arrays.asList(nets));
                    try {
                        byte[] hash = download.getTorrentHash();
                        if (plugin_interface.getShareManager().lookupShare(hash) != null) {
                            is_share = true;
                        }
                    } catch (Throwable e) {
                    }
                }
                String cb_data = download == null ? UrlUtils.getMagnetURI(name, torrent) : UrlUtils.getMagnetURI(download);
                if (download != null) {
                    List<Tag> tags = TagManagerFactory.getTagManager().getTagsForTaggable(TagType.TT_DOWNLOAD_MANUAL, PluginCoreUtils.unwrap(download));
                    for (Tag tag : tags) {
                        if (tag.isPublic()) {
                            cb_data += "&tag=" + UrlUtils.encode(tag.getTagName(true));
                        }
                    }
                }
                String sources = sources_param.getValue();
                boolean add_sources = sources.equals("2") || (sources.equals("1") && is_share);
                if (add_sources) {
                    if (networks.isEmpty()) {
                        for (String net : AENetworkClassifier.AT_NETWORKS) {
                            if (isNetworkEnabled(net)) {
                                networks.add(net);
                            }
                        }
                    }
                    if (networks.contains(AENetworkClassifier.AT_PUBLIC) && !cb_data.contains("xsource=")) {
                        InetAddress ip = NetworkAdmin.getSingleton().getDefaultPublicAddress();
                        InetAddress ip_v6 = NetworkAdmin.getSingleton().getDefaultPublicAddressV6();
                        int port = TCPNetworkManager.getSingleton().getTCPListeningPortNumber();
                        if (ip != null && port > 0) {
                            cb_data += "&xsource=" + UrlUtils.encode(ip.getHostAddress() + ":" + port);
                        }
                        if (ip_v6 != null && port > 0) {
                            cb_data += "&xsource=" + UrlUtils.encode(ip_v6.getHostAddress() + ":" + port);
                        }
                        int extra = sources_extra_param.getValue();
                        if (extra > 0) {
                            if (download == null) {
                                if (torrent != null) {
                                    download = plugin_interface.getDownloadManager().getDownload(torrent);
                                }
                            }
                            if (download != null) {
                                Set<String> added = new HashSet<>();
                                DownloadManager dm = PluginCoreUtils.unwrap(download);
                                PEPeerManager pm = dm.getPeerManager();
                                if (pm != null) {
                                    List<PEPeer> peers = pm.getPeers();
                                    for (PEPeer peer : peers) {
                                        String peer_ip = peer.getIp();
                                        if (AENetworkClassifier.categoriseAddress(peer_ip) == AENetworkClassifier.AT_PUBLIC) {
                                            int peer_port = peer.getTCPListenPort();
                                            if (peer_port > 0) {
                                                cb_data += "&xsource=" + UrlUtils.encode(peer_ip + ":" + peer_port);
                                                added.add(peer_ip);
                                                extra--;
                                                if (extra == 0) {
                                                    break;
                                                }
                                            }
                                        }
                                    }
                                }
                                if (extra > 0) {
                                    Map response_cache = dm.getDownloadState().getTrackerResponseCache();
                                    if (response_cache != null) {
                                        List<TRTrackerAnnouncerResponsePeer> peers = TRTrackerAnnouncerFactory.getCachedPeers(response_cache);
                                        for (TRTrackerAnnouncerResponsePeer peer : peers) {
                                            String peer_ip = peer.getAddress();
                                            if (AENetworkClassifier.categoriseAddress(peer_ip) == AENetworkClassifier.AT_PUBLIC) {
                                                if (!added.contains(peer_ip)) {
                                                    int peer_port = peer.getPort();
                                                    if (peer_port > 0) {
                                                        cb_data += "&xsource=" + UrlUtils.encode(peer_ip + ":" + peer_port);
                                                        added.add(peer_ip);
                                                        extra--;
                                                        if (extra == 0) {
                                                            break;
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
                // removed this as well - nothing wrong with allowing magnet copy
                // for private torrents - they still can't be tracked if you don't
                // have permission
                /*if ( torrent.isPrivate()){

							cb_data = getMessageText( "private_torrent" );

						}else if ( torrent.isDecentralised()){
						*/
                // ok
                /* relaxed this as we allow such torrents to be downloaded via magnet links
							 * (as opposed to tracked in the DHT)

						}else if ( torrent.isDecentralisedBackupEnabled()){

							TorrentAttribute ta_peer_sources 	= plugin_interface.getTorrentManager().getAttribute( TorrentAttribute.TA_PEER_SOURCES );

							String[]	sources = download.getListAttribute( ta_peer_sources );

							boolean	ok = false;

							for (int i=0;i<sources.length;i++){

								if ( sources[i].equalsIgnoreCase( "DHT")){

									ok	= true;

									break;
								}
							}

							if ( !ok ){

								cb_data = getMessageText( "decentral_disabled" );
							}
						}else{

							cb_data = getMessageText( "decentral_backup_disabled" );
							*/
                // }
                // System.out.println( "MagnetPlugin: export = " + url );
                cb_all_data += (cb_all_data.length() == 0 ? "" : "\n") + cb_data;
            }
            try {
                plugin_interface.getUIManager().copyToClipBoard(cb_all_data);
            } catch (Throwable e) {
                e.printStackTrace();
            }
        }
    };
    List<TableContextMenuItem> menus = new ArrayList<>();
    for (String table : TableManager.TABLE_MYTORRENTS_ALL) {
        TableContextMenuItem menu = plugin_interface.getUIManager().getTableManager().addContextMenuItem(table, "MagnetPlugin.contextmenu.exporturi");
        menu.addMultiListener(listener);
        menu.setHeaderCategory(MenuItem.HEADER_SOCIAL);
        menus.add(menu);
    }
    uri_handler.addListener(new MagnetURIHandlerListener() {

        @Override
        public byte[] badge() {
            InputStream is = getClass().getClassLoader().getResourceAsStream("com/biglybt/plugin/magnet/Magnet.gif");
            if (is == null) {
                return (null);
            }
            try {
                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                try {
                    byte[] buffer = new byte[8192];
                    while (true) {
                        int len = is.read(buffer);
                        if (len <= 0) {
                            break;
                        }
                        baos.write(buffer, 0, len);
                    }
                } finally {
                    is.close();
                }
                return (baos.toByteArray());
            } catch (Throwable e) {
                Debug.printStackTrace(e);
                return (null);
            }
        }

        @Override
        public byte[] download(MagnetURIHandlerProgressListener muh_listener, byte[] hash, String args, InetSocketAddress[] sources, long timeout) throws MagnetURIHandlerException {
            try {
                Download dl = plugin_interface.getDownloadManager().getDownload(hash);
                if (dl != null) {
                    Torrent torrent = dl.getTorrent();
                    if (torrent != null) {
                        byte[] torrent_data = torrent.writeToBEncodedData();
                        torrent_data = addTrackersAndWebSeedsEtc(torrent_data, args, new HashSet<String>());
                        return (torrent_data);
                    }
                }
            } catch (Throwable e) {
                Debug.printStackTrace(e);
            }
            return (recoverableDownload(muh_listener, hash, args, sources, timeout, false));
        }

        @Override
        public boolean download(URL url) throws MagnetURIHandlerException {
            try {
                plugin_interface.getDownloadManager().addDownload(url, false);
                return (true);
            } catch (DownloadException e) {
                throw (new MagnetURIHandlerException("Operation failed", e));
            }
        }

        @Override
        public boolean set(String name, Map values) {
            List l = listeners.getList();
            for (int i = 0; i < l.size(); i++) {
                if (((MagnetPluginListener) l.get(i)).set(name, values)) {
                    return (true);
                }
            }
            return (false);
        }

        @Override
        public int get(String name, Map values) {
            List l = listeners.getList();
            for (int i = 0; i < l.size(); i++) {
                int res = ((MagnetPluginListener) l.get(i)).get(name, values);
                if (res != Integer.MIN_VALUE) {
                    return (res);
                }
            }
            return (Integer.MIN_VALUE);
        }
    });
    plugin_interface.getUIManager().addUIListener(new UIManagerListener() {

        @Override
        public void UIAttached(UIInstance instance) {
            if (instance.getUIType().equals(UIInstance.UIT_SWT)) {
                try {
                    Class.forName("com.biglybt.plugin.magnet.swt.MagnetPluginUISWT").getConstructor(new Class[] { UIInstance.class, TableContextMenuItem[].class }).newInstance(new Object[] { instance, menus.toArray(new TableContextMenuItem[menus.size()]) });
                } catch (Throwable e) {
                    e.printStackTrace();
                }
            }
        }

        @Override
        public void UIDetached(UIInstance instance) {
        }
    });
    final List<Download> to_delete = new ArrayList<>();
    Download[] downloads = plugin_interface.getDownloadManager().getDownloads();
    for (Download download : downloads) {
        if (download.getFlag(Download.FLAG_METADATA_DOWNLOAD)) {
            to_delete.add(download);
        }
    }
    final AESemaphore delete_done = new AESemaphore("delete waiter");
    if (to_delete.size() > 0) {
        AEThread2 t = new AEThread2("MagnetPlugin:delmds", true) {

            @Override
            public void run() {
                try {
                    for (Download download : to_delete) {
                        try {
                            download.stop();
                        } catch (Throwable e) {
                        }
                        try {
                            download.remove(true, true);
                        } catch (Throwable e) {
                            Debug.out(e);
                        }
                    }
                } finally {
                    delete_done.release();
                }
            }
        };
        t.start();
    } else {
        delete_done.release();
    }
    plugin_interface.addListener(new PluginListener() {

        @Override
        public void initializationComplete() {
            // make sure DDB is initialised as we need it to register its
            // transfer types
            AEThread2 t = new AEThread2("MagnetPlugin:init", true) {

                @Override
                public void run() {
                    delete_done.reserve();
                    recoverDownloads();
                    plugin_interface.getDistributedDatabase();
                }
            };
            t.start();
        }

        @Override
        public void closedownInitiated() {
        }

        @Override
        public void closedownComplete() {
        }
    });
}
Also used : Torrent(com.biglybt.pif.torrent.Torrent) TOTorrent(com.biglybt.core.torrent.TOTorrent) PEPeer(com.biglybt.core.peer.PEPeer) ShareResourceDir(com.biglybt.pif.sharing.ShareResourceDir) InetSocketAddress(java.net.InetSocketAddress) LocaleUtilities(com.biglybt.pif.utils.LocaleUtilities) DownloadManager(com.biglybt.core.download.DownloadManager) DownloadException(com.biglybt.pif.download.DownloadException) MenuItemListener(com.biglybt.pif.ui.menus.MenuItemListener) UIInstance(com.biglybt.pif.ui.UIInstance) MagnetURIHandler(com.biglybt.net.magneturi.MagnetURIHandler) TableRow(com.biglybt.pif.ui.tables.TableRow) PEPeerManager(com.biglybt.core.peer.PEPeerManager) InetAddress(java.net.InetAddress) ShareResourceFile(com.biglybt.pif.sharing.ShareResourceFile) MagnetURIHandlerProgressListener(com.biglybt.net.magneturi.MagnetURIHandlerProgressListener) TableContextMenuItem(com.biglybt.pif.ui.tables.TableContextMenuItem) URL(java.net.URL) PluginListener(com.biglybt.pif.PluginListener) ShareException(com.biglybt.pif.sharing.ShareException) LocaleListener(com.biglybt.pif.utils.LocaleListener) Download(com.biglybt.pif.download.Download) ShareResource(com.biglybt.pif.sharing.ShareResource) InputStream(java.io.InputStream) TableContextMenuItem(com.biglybt.pif.ui.tables.TableContextMenuItem) MenuItem(com.biglybt.pif.ui.menus.MenuItem) ByteArrayOutputStream(java.io.ByteArrayOutputStream) BooleanParameter(com.biglybt.pif.ui.config.BooleanParameter) TorrentAttribute(com.biglybt.pif.torrent.TorrentAttribute) BooleanParameter(com.biglybt.pif.ui.config.BooleanParameter) Parameter(com.biglybt.pif.ui.config.Parameter) StringListParameter(com.biglybt.pif.ui.config.StringListParameter) IntParameter(com.biglybt.pif.ui.config.IntParameter) TRTrackerAnnouncerResponsePeer(com.biglybt.core.tracker.client.TRTrackerAnnouncerResponsePeer) Tag(com.biglybt.core.tag.Tag) MagnetURIHandlerListener(com.biglybt.net.magneturi.MagnetURIHandlerListener) MagnetURIHandlerException(com.biglybt.net.magneturi.MagnetURIHandlerException) UIManagerListener(com.biglybt.pif.ui.UIManagerListener) BasicPluginConfigModel(com.biglybt.pif.ui.model.BasicPluginConfigModel)

Example 2 with MagnetURIHandlerException

use of com.biglybt.net.magneturi.MagnetURIHandlerException in project BiglyBT by BiglySoftware.

the class MagnetPlugin method _downloadSupport.

private DownloadResult _downloadSupport(final MagnetPluginProgressListener listener, final byte[] hash, final String args, final InetSocketAddress[] sources, long _timeout, int flags) throws MagnetURIHandlerException {
    final long timeout;
    if (_timeout < 0) {
        // use plugin defined value
        int secs = timeout_param.getValue();
        if (secs <= 0) {
            timeout = Integer.MAX_VALUE;
        } else {
            timeout = secs * 1000L;
        }
    } else {
        timeout = _timeout;
    }
    boolean md_enabled;
    final boolean dummy_hash = Arrays.equals(hash, new byte[20]);
    if ((flags & FL_DISABLE_MD_LOOKUP) != 0) {
        md_enabled = false;
    } else {
        md_enabled = md_lookup.getValue() && FeatureAvailability.isMagnetMDEnabled();
    }
    final byte[][] result_holder = { null };
    final Throwable[] result_error = { null };
    final boolean[] manually_cancelled = { false };
    TimerEvent md_delay_event = null;
    final MagnetPluginMDDownloader[] md_downloader = { null };
    boolean net_pub_default = isNetworkEnabled(AENetworkClassifier.AT_PUBLIC);
    final Set<String> networks_enabled;
    final Set<String> additional_networks = new HashSet<>();
    if (args != null) {
        String[] bits = args.split("&");
        List<URL> fl_args = new ArrayList<>();
        Set<String> tr_networks = new HashSet<>();
        Set<String> explicit_networks = new HashSet<>();
        for (String bit : bits) {
            if (bit.startsWith("maggot_sha1")) {
                tr_networks.clear();
                explicit_networks.clear();
                fl_args.clear();
                explicit_networks.add(AENetworkClassifier.AT_I2P);
                break;
            }
            String[] x = bit.split("=");
            if (x.length == 2) {
                String lhs = x[0].toLowerCase();
                if (lhs.equals("fl") || lhs.equals("xs") || lhs.equals("as")) {
                    try {
                        URL url = new URL(UrlUtils.decode(x[1]));
                        fl_args.add(url);
                        tr_networks.add(AENetworkClassifier.categoriseAddress(url.getHost()));
                    } catch (Throwable e) {
                    }
                } else if (lhs.equals("tr")) {
                    try {
                        tr_networks.add(AENetworkClassifier.categoriseAddress(new URL(UrlUtils.decode(x[1])).getHost()));
                    } catch (Throwable e) {
                    }
                } else if (lhs.equals("net")) {
                    String network = AENetworkClassifier.internalise(x[1]);
                    if (network != null) {
                        explicit_networks.add(network);
                    }
                }
            }
        }
        if (explicit_networks.size() > 0) {
            networks_enabled = explicit_networks;
        } else {
            networks_enabled = tr_networks;
            if (net_pub_default) {
                if (networks_enabled.size() == 0) {
                    networks_enabled.add(AENetworkClassifier.AT_PUBLIC);
                }
            } else {
                networks_enabled.remove(AENetworkClassifier.AT_PUBLIC);
            }
        }
        if (fl_args.size() > 0) {
            final AESemaphore fl_sem = new AESemaphore("fl_sem");
            int fl_run = 0;
            for (int i = 0; i < fl_args.size() && i < 3; i++) {
                final URL fl_url = fl_args.get(i);
                String url_net = AENetworkClassifier.categoriseAddress(fl_url.getHost());
                if (networks_enabled.contains(url_net)) {
                    new AEThread2("Magnet:fldl", true) {

                        @Override
                        public void run() {
                            try {
                                TOTorrent torrent = TorrentUtils.download(fl_url, timeout);
                                if (torrent != null) {
                                    if (dummy_hash || Arrays.equals(torrent.getHash(), hash)) {
                                        synchronized (result_holder) {
                                            result_holder[0] = BEncoder.encode(torrent.serialiseToMap());
                                        }
                                    }
                                }
                            } catch (Throwable e) {
                                Debug.out(e);
                            } finally {
                                fl_sem.release();
                            }
                        }
                    }.start();
                    fl_run++;
                }
            }
            if (dummy_hash) {
                long remaining = timeout;
                for (int i = 0; i < fl_run && remaining > 0; i++) {
                    long start = SystemTime.getMonotonousTime();
                    if (!fl_sem.reserve(remaining)) {
                        break;
                    }
                    remaining -= (SystemTime.getMonotonousTime() - start);
                    synchronized (result_holder) {
                        if (result_holder[0] != null) {
                            return (new DownloadResult(result_holder[0], networks_enabled, additional_networks));
                        }
                    }
                }
            }
        }
    } else {
        networks_enabled = new HashSet<>();
        if (net_pub_default) {
            networks_enabled.add(AENetworkClassifier.AT_PUBLIC);
        }
    }
    if (dummy_hash) {
        return (null);
    }
    if (md_enabled) {
        int delay_millis;
        if ((flags & FL_NO_MD_LOOKUP_DELAY) != 0) {
            delay_millis = 0;
        } else {
            delay_millis = md_lookup_delay.getValue() * 1000;
        }
        md_delay_event = SimpleTimer.addEvent("MagnetPlugin:md_delay", delay_millis <= 0 ? 0 : (SystemTime.getCurrentTime() + delay_millis), new TimerEventPerformer() {

            @Override
            public void perform(TimerEvent event) {
                MagnetPluginMDDownloader mdd;
                synchronized (md_downloader) {
                    if (event.isCancelled()) {
                        return;
                    }
                    md_downloader[0] = mdd = new MagnetPluginMDDownloader(MagnetPlugin.this, plugin_interface, hash, networks_enabled, sources, args);
                }
                if (listener != null) {
                    listener.reportActivity(getMessageText("report.md.starts"));
                }
                mdd.start(new MagnetPluginMDDownloader.DownloadListener() {

                    @Override
                    public void reportProgress(int downloaded, int total_size) {
                        if (listener != null) {
                            listener.reportActivity(getMessageText("report.md.progress", String.valueOf(downloaded + "/" + total_size)));
                            listener.reportCompleteness(100 * downloaded / total_size);
                        }
                    }

                    @Override
                    public void complete(TOTorrent torrent, Set<String> peer_networks) {
                        if (listener != null) {
                            listener.reportActivity(getMessageText("report.md.done"));
                        }
                        synchronized (result_holder) {
                            additional_networks.addAll(peer_networks);
                            try {
                                result_holder[0] = BEncoder.encode(torrent.serialiseToMap());
                            } catch (Throwable e) {
                                Debug.out(e);
                            }
                        }
                    }

                    @Override
                    public void failed(boolean mc, Throwable e) {
                        if (listener != null) {
                            listener.reportActivity(getMessageText("report.error", Debug.getNestedExceptionMessage(e)));
                        }
                        synchronized (result_holder) {
                            manually_cancelled[0] = mc;
                            result_error[0] = e;
                        }
                    }
                });
            }
        });
    }
    try {
        try {
            long remaining = timeout;
            boolean sl_enabled = secondary_lookup.getValue() && FeatureAvailability.isMagnetSLEnabled();
            boolean sl_failed = false;
            long secondary_lookup_time = -1;
            final Object[] secondary_result = { null };
            if (networks_enabled.contains(AENetworkClassifier.AT_PUBLIC)) {
                boolean is_first_download = first_download;
                if (is_first_download) {
                    if (listener != null) {
                        listener.reportActivity(getMessageText("report.waiting_ddb"));
                    }
                    first_download = false;
                }
                final DistributedDatabase db = plugin_interface.getDistributedDatabase();
                if (db.isAvailable()) {
                    final List potential_contacts = new ArrayList();
                    final AESemaphore potential_contacts_sem = new AESemaphore("MagnetPlugin:liveones");
                    final AEMonitor potential_contacts_mon = new AEMonitor("MagnetPlugin:liveones");
                    final int[] outstanding = { 0 };
                    final boolean[] lookup_complete = { false };
                    if (listener != null) {
                        listener.reportActivity(getMessageText("report.searching"));
                    }
                    DistributedDatabaseListener ddb_listener = new DistributedDatabaseListener() {

                        private Set found_set = new HashSet();

                        @Override
                        public void event(DistributedDatabaseEvent event) {
                            int type = event.getType();
                            if (type == DistributedDatabaseEvent.ET_OPERATION_STARTS) {
                                if (sources.length > 0) {
                                    new DelayedEvent("MP:sourceAdd", 10 * 1000, new AERunnable() {

                                        @Override
                                        public void runSupport() {
                                            addExplicitSources();
                                        }
                                    });
                                }
                            } else if (type == DistributedDatabaseEvent.ET_VALUE_READ) {
                                contactFound(event.getValue().getContact());
                            } else if (type == DistributedDatabaseEvent.ET_OPERATION_COMPLETE || type == DistributedDatabaseEvent.ET_OPERATION_TIMEOUT) {
                                if (listener != null) {
                                    listener.reportActivity(getMessageText("report.found", String.valueOf(found_set.size())));
                                }
                                // now inject any explicit sources
                                addExplicitSources();
                                try {
                                    potential_contacts_mon.enter();
                                    lookup_complete[0] = true;
                                } finally {
                                    potential_contacts_mon.exit();
                                }
                                potential_contacts_sem.release();
                            }
                        }

                        protected void addExplicitSources() {
                            for (int i = 0; i < sources.length; i++) {
                                try {
                                    InetSocketAddress source = sources[i];
                                    if (AENetworkClassifier.categoriseAddress(source) == AENetworkClassifier.AT_PUBLIC) {
                                        contactFound(db.importContact(sources[i]));
                                    }
                                } catch (Throwable e) {
                                    Debug.printStackTrace(e);
                                }
                            }
                        }

                        public void contactFound(final DistributedDatabaseContact contact) {
                            String key = contact.getAddress().toString();
                            synchronized (found_set) {
                                if (found_set.contains(key)) {
                                    return;
                                }
                                found_set.add(key);
                            }
                            if (listener != null && listener.verbose()) {
                                listener.reportActivity(getMessageText("report.found", contact.getName()));
                            }
                            try {
                                potential_contacts_mon.enter();
                                outstanding[0]++;
                            } finally {
                                potential_contacts_mon.exit();
                            }
                            contact.isAlive(20 * 1000, new DistributedDatabaseListener() {

                                @Override
                                public void event(DistributedDatabaseEvent event) {
                                    try {
                                        boolean alive = event.getType() == DistributedDatabaseEvent.ET_OPERATION_COMPLETE;
                                        if (listener != null && listener.verbose()) {
                                            listener.reportActivity(getMessageText(alive ? "report.alive" : "report.dead", contact.getName()));
                                        }
                                        try {
                                            potential_contacts_mon.enter();
                                            Object[] entry = new Object[] { Boolean.valueOf(alive), contact };
                                            boolean added = false;
                                            if (alive) {
                                                for (int i = 0; i < potential_contacts.size(); i++) {
                                                    if (!((Boolean) ((Object[]) potential_contacts.get(i))[0]).booleanValue()) {
                                                        potential_contacts.add(i, entry);
                                                        added = true;
                                                        break;
                                                    }
                                                }
                                            }
                                            if (!added) {
                                                // dead at end
                                                potential_contacts.add(entry);
                                            }
                                        } finally {
                                            potential_contacts_mon.exit();
                                        }
                                    } finally {
                                        try {
                                            potential_contacts_mon.enter();
                                            outstanding[0]--;
                                        } finally {
                                            potential_contacts_mon.exit();
                                        }
                                        potential_contacts_sem.release();
                                    }
                                }
                            });
                        }
                    };
                    db.read(ddb_listener, db.createKey(hash, "Torrent download lookup for '" + ByteFormatter.encodeString(hash) + "'"), timeout, DistributedDatabase.OP_EXHAUSTIVE_READ | DistributedDatabase.OP_PRIORITY_HIGH);
                    long overall_start = SystemTime.getMonotonousTime();
                    long last_found = -1;
                    AsyncDispatcher dispatcher = new AsyncDispatcher();
                    while (remaining > 0) {
                        try {
                            potential_contacts_mon.enter();
                            if (lookup_complete[0] && potential_contacts.size() == 0 && outstanding[0] == 0) {
                                break;
                            }
                        } finally {
                            potential_contacts_mon.exit();
                        }
                        while (remaining > 0) {
                            if (listener != null && listener.cancelled()) {
                                return (null);
                            }
                            synchronized (result_holder) {
                                if (result_holder[0] != null) {
                                    return (new DownloadResult(result_holder[0], networks_enabled, additional_networks));
                                }
                                if (manually_cancelled[0]) {
                                    throw (new Exception("Manually cancelled"));
                                }
                            }
                            long wait_start = SystemTime.getMonotonousTime();
                            boolean got_sem = potential_contacts_sem.reserve(1000);
                            long now = SystemTime.getMonotonousTime();
                            remaining -= (now - wait_start);
                            if (got_sem) {
                                last_found = now;
                                break;
                            } else {
                                if (sl_enabled) {
                                    if (secondary_lookup_time == -1) {
                                        long base_time;
                                        if (last_found == -1 || now - overall_start > 60 * 1000) {
                                            base_time = overall_start;
                                        } else {
                                            base_time = last_found;
                                        }
                                        long time_so_far = now - base_time;
                                        if (time_so_far > SECONDARY_LOOKUP_DELAY) {
                                            secondary_lookup_time = SystemTime.getMonotonousTime();
                                            doSecondaryLookup(listener, secondary_result, hash, networks_enabled, args);
                                        }
                                    } else {
                                        try {
                                            byte[] torrent = getSecondaryLookupResult(secondary_result);
                                            if (torrent != null) {
                                                return (new DownloadResult(torrent, networks_enabled, additional_networks));
                                            }
                                        } catch (ResourceDownloaderException e) {
                                            sl_failed = true;
                                        // ignore, we just continue processing
                                        }
                                    }
                                }
                                continue;
                            }
                        }
                        if (sl_enabled) {
                            try {
                                byte[] torrent = getSecondaryLookupResult(secondary_result);
                                if (torrent != null) {
                                    return (new DownloadResult(torrent, networks_enabled, additional_networks));
                                }
                            } catch (ResourceDownloaderException e) {
                                sl_failed = true;
                            }
                        }
                        final DistributedDatabaseContact contact;
                        final boolean live_contact;
                        try {
                            potential_contacts_mon.enter();
                            if (potential_contacts.size() == 0) {
                                if (outstanding[0] == 0) {
                                    break;
                                } else {
                                    continue;
                                }
                            } else {
                                Object[] entry = (Object[]) potential_contacts.remove(0);
                                live_contact = ((Boolean) entry[0]).booleanValue();
                                contact = (DistributedDatabaseContact) entry[1];
                            }
                        } finally {
                            potential_contacts_mon.exit();
                        }
                        // System.out.println( "magnetDownload: " + contact.getName() + ", live = " + live_contact );
                        final AESemaphore contact_sem = new AESemaphore("MD:contact");
                        dispatcher.dispatch(new AERunnable() {

                            @Override
                            public void runSupport() {
                                try {
                                    if (!live_contact) {
                                        if (listener != null) {
                                            listener.reportActivity(getMessageText("report.tunnel", contact.getName()));
                                        }
                                        contact.openTunnel();
                                    }
                                    try {
                                        if (listener != null) {
                                            listener.reportActivity(getMessageText("report.downloading", contact.getName()));
                                        }
                                        DistributedDatabaseValue value = contact.read(listener == null ? null : new DistributedDatabaseProgressListener() {

                                            @Override
                                            public void reportSize(long size) {
                                                listener.reportSize(size);
                                            }

                                            @Override
                                            public void reportActivity(String str) {
                                                listener.reportActivity(str);
                                            }

                                            @Override
                                            public void reportCompleteness(int percent) {
                                                listener.reportCompleteness(percent);
                                            }
                                        }, db.getStandardTransferType(DistributedDatabaseTransferType.ST_TORRENT), db.createKey(hash, "Torrent download content for '" + ByteFormatter.encodeString(hash) + "'"), timeout);
                                        if (value != null) {
                                            // let's verify the torrent
                                            byte[] data = (byte[]) value.getValue(byte[].class);
                                            try {
                                                TOTorrent torrent = TOTorrentFactory.deserialiseFromBEncodedByteArray(data);
                                                if (Arrays.equals(hash, torrent.getHash())) {
                                                    if (listener != null) {
                                                        listener.reportContributor(contact.getAddress());
                                                    }
                                                    synchronized (result_holder) {
                                                        result_holder[0] = data;
                                                    }
                                                } else {
                                                    if (listener != null) {
                                                        listener.reportActivity(getMessageText("report.error", "torrent invalid (hash mismatch)"));
                                                    }
                                                }
                                            } catch (Throwable e) {
                                                if (listener != null) {
                                                    listener.reportActivity(getMessageText("report.error", "torrent invalid (decode failed)"));
                                                }
                                            }
                                        }
                                    } catch (Throwable e) {
                                        if (listener != null) {
                                            listener.reportActivity(getMessageText("report.error", Debug.getNestedExceptionMessage(e)));
                                        }
                                        Debug.printStackTrace(e);
                                    }
                                } finally {
                                    contact_sem.release();
                                }
                            }
                        });
                        while (true) {
                            if (listener != null && listener.cancelled()) {
                                return (null);
                            }
                            boolean got_sem = contact_sem.reserve(500);
                            synchronized (result_holder) {
                                if (result_holder[0] != null) {
                                    return (new DownloadResult(result_holder[0], networks_enabled, additional_networks));
                                }
                                if (manually_cancelled[0]) {
                                    throw (new Exception("Manually cancelled"));
                                }
                            }
                            if (got_sem) {
                                break;
                            }
                        }
                    }
                } else {
                    if (is_first_download) {
                        if (listener != null) {
                            listener.reportActivity(getMessageText("report.ddb_disabled"));
                        }
                    }
                }
            }
            if (sl_enabled && !sl_failed) {
                if (secondary_lookup_time == -1) {
                    secondary_lookup_time = SystemTime.getMonotonousTime();
                    doSecondaryLookup(listener, secondary_result, hash, networks_enabled, args);
                }
                while (SystemTime.getMonotonousTime() - secondary_lookup_time < SECONDARY_LOOKUP_MAX_TIME) {
                    if (listener != null && listener.cancelled()) {
                        return (null);
                    }
                    try {
                        byte[] torrent = getSecondaryLookupResult(secondary_result);
                        if (torrent != null) {
                            return (new DownloadResult(torrent, networks_enabled, additional_networks));
                        }
                        synchronized (result_holder) {
                            if (result_holder[0] != null) {
                                return (new DownloadResult(result_holder[0], networks_enabled, additional_networks));
                            }
                            if (manually_cancelled[0]) {
                                throw (new Exception("Manually cancelled"));
                            }
                        }
                        Thread.sleep(500);
                    } catch (ResourceDownloaderException e) {
                        // get here when secondary lookup completes with fail
                        sl_failed = true;
                        break;
                    }
                }
            }
            if (md_enabled) {
                while (remaining > 0) {
                    if (listener != null && listener.cancelled()) {
                        return (null);
                    }
                    Thread.sleep(500);
                    remaining -= 500;
                    if (!sl_failed) {
                        try {
                            byte[] torrent = getSecondaryLookupResult(secondary_result);
                            if (torrent != null) {
                                return (new DownloadResult(torrent, networks_enabled, additional_networks));
                            }
                        } catch (ResourceDownloaderException e) {
                            // get here when secondary lookup completes with fail
                            sl_failed = true;
                        }
                    }
                    synchronized (result_holder) {
                        if (result_holder[0] != null) {
                            return (new DownloadResult(result_holder[0], networks_enabled, additional_networks));
                        }
                        if (result_error[0] != null) {
                            break;
                        }
                    }
                }
            }
            // nothing found
            return (null);
        } catch (Throwable e) {
            Debug.printStackTrace(e);
            if (listener != null) {
                listener.reportActivity(getMessageText("report.error", Debug.getNestedExceptionMessage(e)));
            }
            throw (new MagnetURIHandlerException("MagnetURIHandler failed", e));
        }
    } finally {
        synchronized (md_downloader) {
            if (md_delay_event != null) {
                md_delay_event.cancel();
                if (md_downloader[0] != null) {
                    md_downloader[0].cancel();
                }
            }
        }
    }
}
Also used : TOTorrentAnnounceURLSet(com.biglybt.core.torrent.TOTorrentAnnounceURLSet) InetSocketAddress(java.net.InetSocketAddress) URL(java.net.URL) ResourceDownloaderException(com.biglybt.pif.utils.resourcedownloader.ResourceDownloaderException) MagnetURIHandlerException(com.biglybt.net.magneturi.MagnetURIHandlerException) NoRouteToHostException(java.net.NoRouteToHostException) ShareException(com.biglybt.pif.sharing.ShareException) DownloadException(com.biglybt.pif.download.DownloadException) ResourceDownloaderException(com.biglybt.pif.utils.resourcedownloader.ResourceDownloaderException) TOTorrent(com.biglybt.core.torrent.TOTorrent) MagnetURIHandlerException(com.biglybt.net.magneturi.MagnetURIHandlerException)

Example 3 with MagnetURIHandlerException

use of com.biglybt.net.magneturi.MagnetURIHandlerException in project BiglyBT by BiglySoftware.

the class MagnetPlugin method recoverableDownload.

private byte[] recoverableDownload(final MagnetURIHandlerProgressListener muh_listener, final byte[] hash, final String args, final InetSocketAddress[] sources, final long timeout, boolean is_recovering) throws MagnetURIHandlerException {
    boolean recover = magnet_recovery.getValue();
    String hash_str = Base32.encode(hash);
    try {
        if (recover) {
            Map map = new HashMap();
            map.put("hash", hash);
            map.put("args", args);
            List<Map> l_sources = new ArrayList<>();
            map.put("sources", l_sources);
            if (sources != null && sources.length > 0) {
                for (InetSocketAddress isa : sources) {
                    try {
                        Map m = new HashMap();
                        m.put("port", isa.getPort());
                        if (isa.isUnresolved()) {
                            map.put("host", isa.getHostName());
                        } else {
                            InetAddress ia = isa.getAddress();
                            map.put("address", ia.getAddress());
                        }
                        l_sources.add(m);
                    } catch (Throwable e) {
                        Debug.out(e);
                    }
                }
            }
            map.put("timeout", timeout);
            synchronized (download_activities) {
                Map active = COConfigurationManager.getMapParameter("MagnetPlugin.active.magnets", new HashMap());
                active.put(hash_str, map);
                COConfigurationManager.setParameter("MagnetPlugin.active.magnets", active);
            }
            COConfigurationManager.setDirty();
        }
        byte[] result = download(muh_listener == null ? null : new MagnetPluginProgressListener() {

            @Override
            public void reportSize(long size) {
                muh_listener.reportSize(size);
            }

            @Override
            public void reportActivity(String str) {
                muh_listener.reportActivity(str);
            }

            @Override
            public void reportCompleteness(int percent) {
                muh_listener.reportCompleteness(percent);
            }

            @Override
            public void reportContributor(InetSocketAddress address) {
            }

            @Override
            public boolean cancelled() {
                return (muh_listener.cancelled());
            }

            @Override
            public boolean verbose() {
                return (muh_listener.verbose());
            }
        }, hash, args, sources, timeout, is_recovering ? MagnetPlugin.FL_NO_MD_LOOKUP_DELAY : MagnetPlugin.FL_NONE);
        return (result);
    } catch (Throwable e) {
        if (e instanceof MagnetURIHandlerException) {
            throw ((MagnetURIHandlerException) e);
        } else {
            throw (new MagnetURIHandlerException("Magnet download failed", e));
        }
    } finally {
        if (recover) {
            synchronized (download_activities) {
                Map active = COConfigurationManager.getMapParameter("MagnetPlugin.active.magnets", new HashMap());
                active.remove(hash_str);
            }
            COConfigurationManager.setDirty();
        }
    }
}
Also used : InetSocketAddress(java.net.InetSocketAddress) MagnetURIHandlerException(com.biglybt.net.magneturi.MagnetURIHandlerException) InetAddress(java.net.InetAddress)

Aggregations

MagnetURIHandlerException (com.biglybt.net.magneturi.MagnetURIHandlerException)3 InetSocketAddress (java.net.InetSocketAddress)3 TOTorrent (com.biglybt.core.torrent.TOTorrent)2 DownloadException (com.biglybt.pif.download.DownloadException)2 ShareException (com.biglybt.pif.sharing.ShareException)2 InetAddress (java.net.InetAddress)2 URL (java.net.URL)2 DownloadManager (com.biglybt.core.download.DownloadManager)1 PEPeer (com.biglybt.core.peer.PEPeer)1 PEPeerManager (com.biglybt.core.peer.PEPeerManager)1 Tag (com.biglybt.core.tag.Tag)1 TOTorrentAnnounceURLSet (com.biglybt.core.torrent.TOTorrentAnnounceURLSet)1 TRTrackerAnnouncerResponsePeer (com.biglybt.core.tracker.client.TRTrackerAnnouncerResponsePeer)1 MagnetURIHandler (com.biglybt.net.magneturi.MagnetURIHandler)1 MagnetURIHandlerListener (com.biglybt.net.magneturi.MagnetURIHandlerListener)1 MagnetURIHandlerProgressListener (com.biglybt.net.magneturi.MagnetURIHandlerProgressListener)1 PluginListener (com.biglybt.pif.PluginListener)1 Download (com.biglybt.pif.download.Download)1 ShareResource (com.biglybt.pif.sharing.ShareResource)1 ShareResourceDir (com.biglybt.pif.sharing.ShareResourceDir)1