Search in sources :

Example 16 with ResourceDownloaderException

use of com.biglybt.pif.utils.resourcedownloader.ResourceDownloaderException in project BiglyBT by BiglySoftware.

the class ResourceDownloaderURLImpl method getSizeSupport.

protected long getSizeSupport() throws ResourceDownloaderException {
    try {
        String protocol = original_url.getProtocol().toLowerCase();
        if (protocol.equals("magnet") || protocol.equals("maggot") || protocol.equals("dht") || protocol.equals("vuze") || protocol.equals("biglybt") || protocol.equals("azplug") || protocol.equals("ftp")) {
            return (-1);
        } else if (protocol.equals("file")) {
            return (new File(original_url.toURI()).length());
        }
        reportActivity(this, "Getting size of " + original_url);
        try {
            URL url = new URL(original_url.toString().replaceAll(" ", "%20"));
            url = AddressUtils.adjustURL(url);
            URL initial_url = url;
            PluginProxy plugin_proxy;
            boolean ok = false;
            if (auto_plugin_proxy || isAnonymous()) {
                plugin_proxy = AEProxyFactory.getPluginProxy("downloading resource", url);
                if (plugin_proxy == null) {
                    throw (new ResourceDownloaderException(this, "No plugin proxy available"));
                }
                url = plugin_proxy.getURL();
                force_proxy = plugin_proxy.getProxy();
            } else {
                plugin_proxy = null;
            }
            try {
                if (force_no_proxy) {
                    AEProxySelectorFactory.getSelector().startNoProxy();
                }
                if (auth_supplied) {
                    SESecurityManager.setPasswordHandler(url, this);
                }
                boolean dh_hack = false;
                boolean internal_error_hack = false;
                SSLSocketFactory ssl_socket_factory = null;
                for (int connect_loop = 0; connect_loop < 2; connect_loop++) {
                    try {
                        HttpURLConnection con;
                        if (url.getProtocol().equalsIgnoreCase("https")) {
                            // see ConfigurationChecker for SSL client defaults
                            HttpsURLConnection ssl_con = (HttpsURLConnection) openConnection(force_proxy, url);
                            if (ssl_socket_factory != null) {
                                ssl_con.setSSLSocketFactory(ssl_socket_factory);
                            }
                            if (!internal_error_hack) {
                                ssl_con.setHostnameVerifier(new HostnameVerifier() {

                                    @Override
                                    public boolean verify(String host, SSLSession session) {
                                        return (true);
                                    }
                                });
                            }
                            if (plugin_proxy != null) {
                                TrustManagerFactory tmf = SESecurityManager.getTrustManagerFactory();
                                final List<X509TrustManager> default_tms = new ArrayList<>();
                                if (tmf != null) {
                                    for (TrustManager tm : tmf.getTrustManagers()) {
                                        if (tm instanceof X509TrustManager) {
                                            default_tms.add((X509TrustManager) tm);
                                        }
                                    }
                                }
                                TrustManager[] tms_delegate = SESecurityManager.getAllTrustingTrustManager(new X509TrustManager() {

                                    @Override
                                    public X509Certificate[] getAcceptedIssuers() {
                                        List<X509Certificate> result = new ArrayList<>();
                                        for (X509TrustManager tm : default_tms) {
                                            result.addAll(Arrays.asList(tm.getAcceptedIssuers()));
                                        }
                                        return (result.toArray(new X509Certificate[result.size()]));
                                    }

                                    @Override
                                    public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {
                                        for (X509TrustManager tm : default_tms) {
                                            tm.checkClientTrusted(chain, authType);
                                        }
                                    }

                                    @Override
                                    public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {
                                        for (X509TrustManager tm : default_tms) {
                                            tm.checkServerTrusted(chain, authType);
                                        }
                                    }
                                });
                                SSLContext sc = SSLContext.getInstance("SSL");
                                sc.init(null, tms_delegate, RandomUtils.SECURE_RANDOM);
                                SSLSocketFactory factory = sc.getSocketFactory();
                                ssl_con.setSSLSocketFactory(factory);
                            }
                            if (dh_hack) {
                                UrlUtils.DHHackIt(ssl_con);
                            }
                            if (internal_error_hack && plugin_proxy != null) {
                                String host = plugin_proxy.getURLHostRewrite();
                                UrlUtils.HTTPSURLConnectionSNIHack(host, ssl_con);
                            }
                            con = ssl_con;
                        } else {
                            con = (HttpURLConnection) openConnection(force_proxy, url);
                        }
                        con.setInstanceFollowRedirects(plugin_proxy == null);
                        if (plugin_proxy != null) {
                            con.setRequestProperty("HOST", plugin_proxy.getURLHostRewrite() + (initial_url.getPort() == -1 ? "" : (":" + initial_url.getPort())));
                        }
                        con.setRequestMethod("HEAD");
                        ClientIDGenerator cidg = ClientIDManagerImpl.getSingleton().getGenerator();
                        if (cidg != null) {
                            Properties props = new Properties();
                            cidg.generateHTTPProperties(null, props);
                            String ua = props.getProperty(ClientIDGenerator.PR_USER_AGENT);
                            con.setRequestProperty("User-Agent", ua);
                        }
                        setRequestProperties(con, false);
                        try {
                            con.connect();
                        } catch (AEProxyFactory.UnknownHostException e) {
                            throw (new UnknownHostException(e.getMessage()));
                        }
                        int response = con.getResponseCode();
                        setProperty("URL_HTTP_Response", new Long(response));
                        if ((response != HttpURLConnection.HTTP_ACCEPTED) && (response != HttpURLConnection.HTTP_OK)) {
                            if (response == HttpURLConnection.HTTP_MOVED_TEMP || response == HttpURLConnection.HTTP_MOVED_PERM) {
                                // cheap option for the moment
                                return (-1);
                            }
                            URL dest = url;
                            if (plugin_proxy != null) {
                                try {
                                    dest = new URL(plugin_proxy.getTarget());
                                } catch (Throwable e) {
                                }
                            }
                            throw (new ResourceDownloaderException(this, "Error on connect for '" + trimForDisplay(dest) + "': " + Integer.toString(response) + " " + con.getResponseMessage()));
                        }
                        getRequestProperties(con);
                        ok = true;
                        return (UrlUtils.getContentLength(con));
                    } catch (SSLException e) {
                        String msg = Debug.getNestedExceptionMessage(e);
                        if (connect_loop < 3) {
                            boolean try_again = false;
                            if (msg.contains("DH keypair")) {
                                if (!dh_hack) {
                                    dh_hack = true;
                                    try_again = true;
                                }
                            } else if (msg.contains("internal_error") || msg.contains("handshake_failure")) {
                                if (!internal_error_hack) {
                                    internal_error_hack = true;
                                    try_again = true;
                                }
                            }
                            ssl_socket_factory = SESecurityManager.installServerCertificates(url);
                            if (ssl_socket_factory != null) {
                                // certificate has been installed
                                try_again = true;
                            }
                            if (try_again) {
                                continue;
                            }
                        }
                        throw (e);
                    } catch (IOException e) {
                        if (connect_loop == 0) {
                            URL retry_url = UrlUtils.getIPV4Fallback(url);
                            if (retry_url != null) {
                                url = retry_url;
                                continue;
                            }
                        }
                        throw (e);
                    }
                }
                throw (new ResourceDownloaderException(this, "Should never get here"));
            } finally {
                if (auth_supplied) {
                    SESecurityManager.setPasswordHandler(url, null);
                }
                if (force_no_proxy) {
                    AEProxySelectorFactory.getSelector().endNoProxy();
                }
                if (plugin_proxy != null) {
                    plugin_proxy.setOK(ok);
                    force_proxy = null;
                }
            }
        } catch (java.net.MalformedURLException e) {
            throw (new ResourceDownloaderException(this, "Exception while parsing URL '" + original_url + "':" + e.getMessage(), e));
        } catch (java.net.UnknownHostException e) {
            throw (new ResourceDownloaderException(this, "Exception while initializing download of '" + trimForDisplay(original_url) + "': Unknown Host '" + e.getMessage() + "'", e));
        } catch (java.io.IOException e) {
            throw (new ResourceDownloaderException(this, "I/O Exception while downloading '" + trimForDisplay(original_url) + "'", e));
        }
    } catch (Throwable e) {
        ResourceDownloaderException rde;
        if (e instanceof ResourceDownloaderException) {
            rde = (ResourceDownloaderException) e;
        } else {
            Debug.out(e);
            rde = new ResourceDownloaderException(this, "Unexpected error", e);
        }
        throw (rde);
    }
}
Also used : PluginProxy(com.biglybt.core.proxy.AEProxyFactory.PluginProxy) CertificateException(java.security.cert.CertificateException) java.net(java.net) ClientIDGenerator(com.biglybt.pif.clientid.ClientIDGenerator) ResourceDownloaderException(com.biglybt.pif.utils.resourcedownloader.ResourceDownloaderException) java.io(java.io) X509Certificate(java.security.cert.X509Certificate) AEProxyFactory(com.biglybt.core.proxy.AEProxyFactory)

Example 17 with ResourceDownloaderException

use of com.biglybt.pif.utils.resourcedownloader.ResourceDownloaderException in project BiglyBT by BiglySoftware.

the class UtilitiesImpl method getRSSFeed.

@Override
public RSSFeed getRSSFeed(URL feed_location) throws ResourceDownloaderException, SimpleXMLParserDocumentException {
    String feed_str = feed_location.toExternalForm();
    String lc_feed_str = feed_str.toLowerCase(Locale.US);
    ResourceDownloader rd;
    PluginProxy plugin_proxy = null;
    try {
        if (lc_feed_str.startsWith("tor:")) {
            String target_resource = feed_str.substring(4);
            try {
                feed_location = new URL(target_resource);
            } catch (MalformedURLException e) {
                throw (new ResourceDownloaderException(e));
            }
            Map<String, Object> options = new HashMap<>();
            options.put(AEProxyFactory.PO_PEER_NETWORKS, new String[] { AENetworkClassifier.AT_TOR });
            plugin_proxy = AEProxyFactory.getPluginProxy("RSS Feed download of '" + target_resource + "'", feed_location, options, true);
            if (plugin_proxy == null) {
                throw (new ResourceDownloaderException("No Tor plugin proxy available for '" + feed_str + "'"));
            }
            rd = getResourceDownloaderFactory().create(plugin_proxy.getURL(), plugin_proxy.getProxy());
            rd.setProperty("URL_HOST", plugin_proxy.getURLHostRewrite() + (feed_location.getPort() == -1 ? "" : (":" + feed_location.getPort())));
        } else {
            if (AENetworkClassifier.categoriseAddress(feed_location.getHost()) != AENetworkClassifier.AT_PUBLIC) {
                plugin_proxy = AEProxyFactory.getPluginProxy("RSS Feed download of '" + feed_location + "'", feed_location, true);
                if (plugin_proxy == null) {
                    throw (new ResourceDownloaderException("No Plugin proxy available for '" + feed_str + "'"));
                }
                rd = getResourceDownloaderFactory().create(plugin_proxy.getURL(), plugin_proxy.getProxy());
                rd.setProperty("URL_HOST", plugin_proxy.getURLHostRewrite() + (feed_location.getPort() == -1 ? "" : (":" + feed_location.getPort())));
            } else {
                rd = getResourceDownloaderFactory().create(feed_location);
            }
        }
        return (getRSSFeed(feed_location, rd));
    } finally {
        if (plugin_proxy != null) {
            plugin_proxy.setOK(true);
        }
    }
}
Also used : MalformedURLException(java.net.MalformedURLException) ResourceDownloaderException(com.biglybt.pif.utils.resourcedownloader.ResourceDownloaderException) PluginProxy(com.biglybt.core.proxy.AEProxyFactory.PluginProxy) ResourceDownloader(com.biglybt.pif.utils.resourcedownloader.ResourceDownloader) URL(java.net.URL)

Example 18 with ResourceDownloaderException

use of com.biglybt.pif.utils.resourcedownloader.ResourceDownloaderException in project BiglyBT by BiglySoftware.

the class ResourceDownloaderAlternateImpl method download.

@Override
public InputStream download() throws ResourceDownloaderException {
    if (delegates.length == 0) {
        ResourceDownloaderException error = new ResourceDownloaderException(this, "Alternate download fails - 0 alteratives");
        informFailed(error);
        throw (error);
    }
    asyncDownload();
    done_sem.reserve();
    if (result instanceof InputStream) {
        return ((InputStream) result);
    }
    throw ((ResourceDownloaderException) result);
}
Also used : ResourceDownloaderException(com.biglybt.pif.utils.resourcedownloader.ResourceDownloaderException) InputStream(java.io.InputStream)

Example 19 with ResourceDownloaderException

use of com.biglybt.pif.utils.resourcedownloader.ResourceDownloaderException in project BiglyBT by BiglySoftware.

the class ResourceDownloaderAlternateImpl method getSize.

@Override
public long getSize() throws ResourceDownloaderException {
    if (delegates.length == 0) {
        ResourceDownloaderException error = new ResourceDownloaderException(this, "Alternate download fails - 0 alteratives");
        informFailed(error);
        throw (error);
    }
    if (size != -2) {
        return (size);
    }
    try {
        for (int i = 0; i < max_to_try; i++) {
            try {
                ResourceDownloaderBaseImpl c = ((ResourceDownloaderBaseImpl) delegates[i]).getClone(this);
                addReportListener(c);
                size = c.getSize();
                setProperties(c);
                break;
            } catch (ResourceDownloaderException e) {
                if (i == delegates.length - 1) {
                    throw (e);
                }
            }
        }
    } finally {
        if (size == -2) {
            size = -1;
        }
        setSize(size);
    }
    return (size);
}
Also used : ResourceDownloaderException(com.biglybt.pif.utils.resourcedownloader.ResourceDownloaderException)

Example 20 with ResourceDownloaderException

use of com.biglybt.pif.utils.resourcedownloader.ResourceDownloaderException 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)

Aggregations

ResourceDownloaderException (com.biglybt.pif.utils.resourcedownloader.ResourceDownloaderException)26 ResourceDownloader (com.biglybt.pif.utils.resourcedownloader.ResourceDownloader)13 InputStream (java.io.InputStream)11 URL (java.net.URL)11 ResourceDownloaderAdapter (com.biglybt.pif.utils.resourcedownloader.ResourceDownloaderAdapter)6 ResourceDownloaderFactory (com.biglybt.pif.utils.resourcedownloader.ResourceDownloaderFactory)6 IOException (java.io.IOException)5 ZipInputStream (java.util.zip.ZipInputStream)5 PluginProxy (com.biglybt.core.proxy.AEProxyFactory.PluginProxy)4 TOTorrent (com.biglybt.core.torrent.TOTorrent)4 File (java.io.File)4 ArrayList (java.util.ArrayList)4 LogEvent (com.biglybt.core.logging.LogEvent)3 VuzeFile (com.biglybt.core.vuzefile.VuzeFile)3 Update (com.biglybt.pif.update.Update)3 FileInputStream (java.io.FileInputStream)3 HTMLPage (com.biglybt.core.html.HTMLPage)2 TOTorrentException (com.biglybt.core.torrent.TOTorrentException)2 AEThread (com.biglybt.core.util.AEThread)2 ClientIDGenerator (com.biglybt.pif.clientid.ClientIDGenerator)2