aldenml / libtorrent4j

libtorrent for java, a swig Java interface for libtorrent
http://libtorrent4j.org
Other
204 stars 31 forks source link

Magnet resume data doesn't contain trackers and url seeds #231

Closed proninyaroslav closed 1 year ago

proninyaroslav commented 1 year ago

Since TorrentInfo::bencode has been removed due to libtorrent API changes, the only option is to get bencode with TorrentHandle::saveResumeData(SAVE_INFO_DICT) and then get it asynchronously in SaveResumeDataAlert https://github.com/arvidn/libtorrent/issues/7200. But if the magnet link contains trackers or url seeds in its body, a resume data doesn't contain trackers and url seeds, despite the SAVE_INFO_DICT flag. I thought my magnet fetching code was the problem, but I also checked the default SessionManager::fetchMagnet method (it also uses saveResumeData for extracting bencode) and it returns an empty list of trackers and url seeds even if the magnet contains trackers. At the same time, TorrentInfo::bencode in the old version correctly returned a list of trackers and url seeds.

aldenml commented 1 year ago

Hi @proninyaroslav, try the latest version 2.1.0-28. It works for me, but just in case there is a timing issue in Android, I'm re-populating the information in the fetchMagnet logic (I imagine you can do the same if you have similar code).

https://github.com/aldenml/libtorrent4j/blob/master/src/main/java/org/libtorrent4j/SessionManager.java#L672

proninyaroslav commented 1 year ago

@aldenml I tried this and it turns out it doesn't make sense, since at this point the resumeDataParams already has trackers . As it turns out, the problem occurs elsewhere. When I get the bencode array, I convert it to torrent_info and then pass it to add_torrent_params::set_ti() to add the torrent. And since the trackers and web seeds API have been removed from torrent_info, add_torrent_params will no longer contain trackers and web seeds unless you extract and add them manually. Is there a new way to extract trackers and web seeds from the bencode array if the API has been removed from TorrentInfo?

aldenml commented 1 year ago

Hi @proninyaroslav , I imagine you can always parse manually the bencode array, like it's done internally at https://github.com/aldenml/libtorrent/blob/7faba9c86d65046227a7c86a98b1512bc7202243/src/torrent_info.cpp#L1487

Let me know if that helps, if not, maybe you can point me to your code and maybe we can find an alternative.

proninyaroslav commented 1 year ago

@aldenml I checked the behavior and it turned out that if I create a TorrentInfo object from MappedByteBuffer or File then it contains trackers and they are visible after adding the torrent. If I create a TorrentInfo from a byte array, then it doesn't contain trackers and after adding the torrent they are not there, although they are in bencode at the time the resume data was saved and before being converted to TorrentInfo. In other words, the bencode contains trackers in both cases (file or magnet), but if I create TorrentInfo from a byte array, then it ignores the trackers in the bencode and after adding the torrent they are not in TorrentHandle.

Example:

package org.example;

import org.libtorrent4j.*;
import org.libtorrent4j.alerts.AddTorrentAlert;
import org.libtorrent4j.alerts.Alert;
import org.libtorrent4j.alerts.AlertType;

import java.io.File;
import java.util.concurrent.CountDownLatch;

public class Main {
    public static void main(String[] args) {
        File torrentFile = new File(args[0]);
        File parentDir = torrentFile.getParentFile();
        String magnetUri = "magnet:?xt=urn:btih:3b245504cf5f11bbdbe1201cea6a6bf45aee1bc0&tr=udp%3A%2F%2Ftracker.openbittorrent.com%3A80";

        final SessionManager s = new SessionManager();

        final CountDownLatch signal = new CountDownLatch(2);

        s.addListener(new AlertListener() {
            @Override
            public int[] types() {
                return null;
            }

            @Override
            public void alert(Alert<?> alert) {
                AlertType type = alert.type();

                switch (type) {
                    case ADD_TORRENT:
                        TorrentHandle th = ((AddTorrentAlert) alert).handle();
                        th.pause();
                        System.out.println("Torrent added: " + th.getName());
                        System.out.println("Trackers:");
                        for (AnnounceEntry tracker : th.trackers()) {
                            System.out.println(tracker.url());
                        }
                        signal.countDown();
                        break;
                    case SESSION_STATS:
                        s.postDhtStats();
                        break;
                }
            }
        });

        s.start();
        s.postDhtStats();

        // Add torrent file
        TorrentInfo ti = new TorrentInfo(torrentFile);
        s.download(ti, parentDir);

        // Fetching the magnet uri, waiting 30 seconds max
        byte[] data = s.fetchMagnet(magnetUri, 30, new File("/tmp"));
        // Add magnet
        ti = new TorrentInfo(data);
        s.download(ti, parentDir);

        try {
            signal.await();
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }

        s.stop();
    }
}

Output (first - torrent file, second - magnet) :

Torrent added: AVA Lingerie Autumn Winter Catalog 2016-2017.pdf
Trackers:
http://bt.t-ru.org/ann
http://retracker.local/announce
Torrent added: ubuntu-22.04.1-desktop-amd64.iso
Trackers:
aldenml commented 1 year ago

interesting...thanks for the detailed explanation, let me look deeper at this.

aldenml commented 1 year ago

Hi @proninyaroslav , it was a bug on my side, I was calling the wrong function to save the add_torrent_params. See https://github.com/aldenml/libtorrent4j/pull/241/files#diff-9e306d228fee29b95e8be9a01b188d8dfe0df164081043f3884fc3c934fc9babR671

I will release another version soon.

aldenml commented 1 year ago

@proninyaroslav , give 2.1.0-29 a try and let me know.

proninyaroslav commented 1 year ago

I confirm, it's fixed. thank you!