Giter Site home page Giter Site logo

atomashpolskiy / bt Goto Github PK

View Code? Open in Web Editor NEW
2.4K 86.0 379.0 87.28 MB

BitTorrent library and client with DHT, magnet links, encryption and more

Home Page: https://atomashpolskiy.github.io/bt/

License: Apache License 2.0

Java 99.76% Shell 0.18% PowerShell 0.07%
bittorrent p2p dht torrent-client torrent magnet magnet-link

bt's Introduction

A full-featured BitTorrent implementation in Java 8
peer exchange | magnet links | DHT | encryption | LSD | private trackers | extended protocol | partial downloads | port forwarding

Bt CLI

Linux build Linux build Maven Central JavaDoc Coverage

Supported BEPs and extensions

Resources

  • HOME – website with documentation and tutorials
  • RELEASE NOTES – list of features, bugfixes and improments for each version
  • UPGRADE INSTRUCTIONS – version migration guide
  • FORUM – Google group for support and feedback
  • TROUBLESHOOTING - solutions for some common problems
  • LICENSE – licensed under Apache License 2.0

Runnable apps and demos

Media

Prerequisites

Currently, all peer connections are established via encryption negotation protocol (also called MSE handshake). If you're using Oracle JDK (pre 8u152), in order to be able to connect to peers you must install Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy. The reason for this requirement is that the MSE RC4 cipher uses 160 bit keys, while default Java installation allows at most 128 bit keys.

Usage

Most recent version available in Maven Central is 1.10.

Declare the following dependencies in your project’s pom.xml:

<dependency>
    <groupId>com.github.atomashpolskiy</groupId>
    <artifactId>bt-core</artifactId>
    <version>${bt-version}</version>
</dependency>
<dependency>
    <groupId>com.github.atomashpolskiy</groupId>
    <artifactId>bt-http-tracker-client</artifactId>
    <version>${bt-version}</version>
</dependency>
<dependency>
    <groupId>com.github.atomashpolskiy</groupId>
    <artifactId>bt-dht</artifactId>
    <version>${bt-version}</version>
</dependency>
<dependency>
    <groupId>com.github.atomashpolskiy</groupId>
    <artifactId>bt-upnp</artifactId>
    <version>${bt-version}</version>
</dependency>

Building from source

git clone https://github.com/atomashpolskiy/bt.git
cd bt
mvn clean install -DskipTests

Code sample

Download a torrent from a magnet link

// enable multithreaded verification of torrent data
Config config = new Config() {
    @Override
    public int getNumOfHashingThreads() {
        return Runtime.getRuntime().availableProcessors() * 2;
    }
};

// enable bootstrapping from public routers
Module dhtModule = new DHTModule(new DHTConfig() {
    @Override
    public boolean shouldUseRouterBootstrap() {
        return true;
    }
});

// get download directory
Path targetDirectory = Paths.get(System.getProperty("user.home"), "Downloads");

// create file system based backend for torrent data
Storage storage = new FileSystemStorage(targetDirectory);

// create client with a private runtime
BtClient client = Bt.client()
        .config(config)
        .storage(storage)
        .magnet("magnet:?xt=urn:btih:af0d9aa01a9ae123a73802cfa58ccaf355eb19f1")
        .autoLoadModules()
        .module(dhtModule)
        .stopWhenDownloaded()
        .build();

// launch
client.startAsync().join();

Create a torrent

Path torrentRoot = Paths.get("/home/torrents/mytorrent");
Path file1 = Paths.get("/home/torrents/mytorrent/file1.bin");
Path file2 = Paths.get("/home/torrents/mytorrent/file2.bin");
Path dirToAdd = Paths.get("/home/torrents/mytorrent/dir_with_files");
byte[] torrentBytes = new TorrentBuilder()
        .rootPath(torrentRoot)
        .addFiles(file1, file2, dirToAdd)
        .announce("http://example.com/announce")
        .build();
Files.write(Paths.get("/home/torrents/mytorrent.torrent"), torrentBytes);

What makes Bt stand out from the crowd

Flexibility

Being built around the Guice DI, Bt provides many options for tailoring the system for your specific needs. If something is a part of Bt, then it can be modified or substituted for your custom code.

Custom backends

Bt is shipped with a standard file-system based backend (i.e. you can download the torrent file to a storage device). However, the backend details are abstracted from the message-level code. This means that you can use your own backend by providing a storage unit implementation.

Protocol extensions

One notable customization scenario is extending the standard BitTorrent protocol with your own messages. BitTorrent's BEP-10 provides a native support for protocol extensions, and implementation of this standard is already included in Bt. Contribute your own Messages, byte manipulating MessageHandlers, message consumers and producers; supply any additional info in ExtendedHandshake.

Test infrastructure

To allow you test the changes that you've made to the core, Bt ships with a specialized framework for integration tests. Create an arbitrary-sized swarm of peers inside a simple JUnit test, set the number of seeders and leechers and start a real torrent session on your localhost. E.g. create one seeder and many leechers to stress test the network overhead; use a really large file and multiple peers to stress test your newest laptop's expensive SSD storage; or just launch the whole swarm in no-files mode and test your protocol extensions.

Parallel downloads

Bt has out-of-the-box support for multiple simultaneous torrent sessions with minimal system overhead.

Partial downloads

Bt has an API for selecting only a subset of torrent files to download. See the bt.TorrentClientBuilder.fileSelector(TorrentFileSelector) client builder method. File selection works for both .torrent file-based and magnet link downloads.

Java 8 CompletableFuture

Client API leverages the asynchronous java.util.concurrent.CompletableFuture to provide the most natural way for co-ordinating multiple torrent sessions. E.g. use CompletableFuture.allOf(client1.startAsync(...), client2.startAsync(...), ...).join(). Or create a more sophisticated processing pipeline.

And much more...

Troubleshooting

Can't connect to peers, everything else seems to work

If you're using an Oracle JDK, make sure that you have installed Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy.

Other BitTorrent clients can't connect to a Bt client / No incoming connections when seeding

a) If you're behind a firewall and/or a NAT (e.g. a router), make sure they are configured to allow incoming TCP and UDP connections on the ports used by Bt. Default Bt ports are 6891 and 49001 for BitTorrent and DHT respectively. NAT must additionally be configured to forward all incoming traffic on these ports to the host, that Bt is running on.

b) Many popular BitTorrent clients use UPnP and NAT-PMP to automatically configure port forwarding on NATs. Since 1.8 Bt does this as well, so make sure to include bt-upnp module in the list of dependencies.

There are exceptions in the build log (but the build completes successfully)

This is perfectly fine. Some of the tests verify that the exceptions are thrown in certain cases, hence the exception messages.

Can't run the CLI on Windows XP (java.io.IOException: Cannot run program "/bin/stty")

CLI GUI indeed does not work on Windows XP. Run in headless mode by using -H flag.

Can't connect to peers on Windows 7/8/10

There seem to be some issues with dual-stack networking in Windows JDK (e.g. see this question on SO), with Java trying to use IPv6 address, when it's not really available in the system. The simplest solution is to force Java to use IPv4 by setting java.net.preferIPv4Stack property to true.

Support and feedback

Any thoughts, ideas, criticism, etc. are welcome, as well as votes for new features and BEPs to be added. You have the following options to share your ideas, receive help or report bugs:

Donate

Donate

bt's People

Contributors

atomashpolskiy avatar based2 avatar bbijelic avatar ckovorodkin avatar glromeo avatar manandbytes avatar morrislaw avatar olegandreych avatar phillui-37 avatar pyckle avatar schneems avatar trip-lixia avatar wizzardo avatar yorlov avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

bt's Issues

Incorrect behavior when the same peer participates in more than one torrent

Seams like library doesn't expect, that one peer can be connected to more than one torrent.

PeerConnectionPool is a singleton:

binder.bind(IPeerConnectionPool.class).to(PeerConnectionPool.class).asEagerSingleton();

but mapping don't use TorrentId as a part of the key:
private ConcurrentMap<Peer, PeerConnection> connections;

De-duplication of torrent file metadata

Normalization of file paths is performed in bt.data.file.FileSystemStorage on a per-file basis. For malformed torrents this may lead to having duplicate files and storage units (esp. bad if the duplicate files have different size).

http://retracker.local/announce is ignored

(announce key: [[http://tracker.example/ann], [http://retracker.local/announce]])

If announce key contains two tiers and the first tier contains working tracker, then the current implementation of MultiTracker will ignore (line # 133) the second tier. As a result, hi-speed local peers will not be discovered via http://retracker.local/announce in the ISP's local network. And LSD can't help in this case, because multicast packets will be suppressed in the ISP's local network.

private TrackerResponse tryForAllTrackers(Function<Tracker, TrackerResponse> func) {
List<TrackerResponse> responses = new ArrayList<>();
for (List<Tracker> trackerTier : trackerTiers) {
TrackerResponse response;
Tracker currentTracker;
for (int i = 0; i < trackerTier.size(); i++) {
currentTracker = trackerTier.get(i);
response = func.apply(currentTracker);
responses.add(response);
if (response.isSuccess()) {
if (trackerTier.size() > 1) {
trackerTier.remove(i);
trackerTier.add(0, currentTracker);
}
return response;
} else if (response.getError().isPresent()) {
Throwable e = response.getError().get();
LOGGER.warn("Unexpected error during interaction with the tracker: " + currentTracker, e);
} else {
LOGGER.warn("Unexpected error during interaction with the tracker: " + currentTracker +
"; message: " + response.getErrorMessage());
}
}
}
throw new BtException("All trackers failed; responses (in chrono order): " + responses);
}

That use case isn't covered in http://www.bittorrent.org/beps/bep_0012.html
And is not taken into account in http://archive.is/GeZVd

PS

if (trackerTier.size() > 1 
        && i != 0 // ;-)
        ) {
    trackerTier.remove(i);
    trackerTier.add(0, currentTracker);
}

java.lang.IllegalAccessError when running inside JBoss modules

I get the following exception when running with bt-dht inside JBoss modules:

Exception in thread "main" java.lang.IllegalAccessError: class bt.protocol.handler.PortMessageHandler cannot access its superclass bt.protocol.handler.UniqueMessageHandler

Although these classes are both in the same java package, they belong to different modules. Making UniqueMessageHandler public would solve this problem.

I guess that the same issue can be triggered using OSGI or Jigsaw.

Randomized rarest-first selector behaves like a sequential selector when peers are seeds

On behalf of @ckovorodkin

Randomized flavor of bt.torrent.selector.RarestFirstSelector acts much like a sequential rarest-first selector, when most of the peers are seeds, and many or all pieces are equally available. The rarest-first selector would then choose pieces in a sequential fashion:

N = 10
while pieces is not an empty list
    select and remove random piece with index K between 0 and N
    shift all elements with index greater than K to left

E.g. in the simplest case there is one seed, and each piece has availability of 1. It's easy to see that the order of selection will always be skewed to lower indices (because the set of possible next pieces is handicapped by N first elements).

Torrent processing chain

Need to introduce a notion of torrent processing chain with clearly separated stages: metadata retrieval, torrent parsing, download, finalization. Library client will be able to register listeners that will receive the results of a particular stage. For instance, this might make it possible for the user to select specific files that should be downloaded from a multi-file torrent. Another example would be to move/rename the temporary download files (if we decide to add such option) after the download is complete.

Validation of bitfield message

BitfieldHandler doesn't validate received message.

https://wiki.theory.org/index.php/BitTorrentSpecification#bitfield:_.3Clen.3D0001.2BX.3E.3Cid.3D5.3E.3Cbitfield.3E

A bitfield of the wrong length is considered an error. Clients should drop the connection if they receive bitfields that are not of the correct size, or if the bitfield has any of the spare bits set.

// bitfield: <len=0001+X><id=5><bitfield>
private static int decodeBitfield(DecodingContext context, ByteBuffer buffer, int length) {
int consumed = 0;
if (buffer.remaining() >= length) {
byte[] bitfield = new byte[length];
buffer.get(bitfield);
context.setMessage(new Bitfield(bitfield));
consumed = length;
}
return consumed;
}

NPE in DefaultChannelPipeline when there are unprocessed leftovers from MSE handshake

decoders assigned after fireDataReceived()

fireDataReceived();
this.outboundBuffer = outboundBuffer;
this.decoders = decoders;

But fireDataReceived() can use decoders
this.inboundBuffer = inboundBuffer;
// process existing data immediately (e.g. there might be leftovers from MSE handshake)
fireDataReceived();
this.outboundBuffer = outboundBuffer;
this.decoders = decoders;
this.encoders = encoders;
this.inboundQueue = new LinkedBlockingQueue<>();
}
@Override
public Message decode() {
checkHandlerIsBound();
return inboundQueue.poll();
}
private void fireDataReceived() {
ByteBuffer buffer = inboundBuffer.lockAndGet();
try {
processInboundData(buffer);
} finally {
inboundBuffer.unlock();
}
}
private void processInboundData(ByteBuffer buffer) {
int undecodedDataLimit = buffer.position();
if (undecodedDataOffset < undecodedDataLimit) {
buffer.flip();
decoders.forEach(mutator -> {

More sophisticated network binding

From #20:

Not sure if this is expected to work, but I tried with "-i eth1" and I get "Failed to parse the acceptor's internet address". It would be convenient if it could resolve iface name -> ip address.

Currently local address is set in bt.runtime.Config#acceptorAddress. It's used for:

  • binding an incoming connections acceptor
  • establishing outgoing peer connections
  • http tracker requests
  • udp tracker requests
  • binding DHT agent

Maybe we could provide a more sophisticated configuration, that would allow to specify a list of rules: internet addresses, address + network mask pairs, interface names, plus optionally the preferred address family.

Regarding the address selection algorithm, there are two possible implementations:

  1. Compile the list of rules to a java.function.Predicate<InetAddress> and use it to filter and select one appropriate address from those, that are available on the host. See DHTConfiguration in mldht and the corresponding issue for inspiration.
  2. Use the list of rules to traverse available addresses and select the first match. I personally prefer this one, despite it being O(mn) instead of O(n).

Torrent metadata serializer

When a torrent is created programmatically and not from a real binary source (like a .torrent file), we still need at least the info dictionary part to exchange metadata with peers. Would be convenient to have a dedicated Formatter/Serializer, that will handle translation of Torrent object into a byte array (deserialization is handled by MetadataService and uses YML schemas and object models for validation -- this logic can be externalized from MetadataService, which would instead be a factory for formatters/serializers). There's no real need for this right now, just an idea for a future enhancement.

CLI not downloading

I actually tried used some code from bt-cli source code and there was no progress in download in my program.

I was confused. So I tried the actual bt-cli from terminal using it's jar and it's giving the same result - no progress in download. No increase in download speed too.

Why is this happening ?

Incorrent statistic tracking in BitfieldBasedStatistics

From time to time peerBitfields.put(peer, bitfield); replaces previous value and drop out it without updating pieceTotals[]

public void addBitfield(Peer peer, Bitfield bitfield) {
validateBitfieldLength(bitfield);
peerBitfields.put(peer, bitfield);
for (int i = 0; i < pieceTotals.length; i++) {
if (bitfield.getPieceStatus(i) == PieceStatus.COMPLETE_VERIFIED) {
incrementPieceTotal(i);
}
}
}

Seams like incorrect usage of BitfieldBasedStatistics.

Download not starting when using standalone client with private runtime

Hi @atomashpolskiy ,

I would be very thankful for little assistance. Not sure if I'm missing something.

I'm trying to setup simple example you provided, but it fails to start download either by using torrent file or magnet link.

It just starts and hangs at one point, no download has started. I can confirm that magnet url works with e.g. uTorrent application.

JCE has been installed and verified by checking max key sizes.

Environment

OS: Windows 10
Java: Oracle JDK 8u144 + JCE
Windows firewall = disabled (for testing purposes)

Using Bt release from 2017-08-11: 1.3.1, was also not working with 1.3 version.

Example code:

package com.github.bbijelic.torrent;

import java.io.File;

import bt.Bt;
import bt.data.Storage;
import bt.data.file.FileSystemStorage;
import bt.runtime.BtClient;
import bt.torrent.selector.SequentialSelector;

public class TorrentClient {

	public static void main(String[] args) {

		String magnetLink = "magnet:?xt=urn:btih:2b32e64f6cd755a9e54d60e205a9681d6670cfae";
		Storage storage = new FileSystemStorage(new File("C:\\Users\\Snijele\\Desktop\\TEST"));
		BtClient client = Bt.client().storage(storage).magnet(magnetLink)
				.autoLoadModules().build();

		// launch
		client.startAsync(state -> {
			if (state.getPiecesRemaining() == 0) {
				client.stop();
			}
		}, 1000).join();
	}

}

Log output:

20:35:03.443 [main] INFO bt.runtime.BtRuntimeBuilder - Auto-loading module bt.tracker.http.HttpTrackerModule with default configuration
20:35:03.448 [main] INFO bt.runtime.BtRuntimeBuilder - Auto-loading module bt.peerexchange.PeerExchangeModule with default configuration
20:35:03.916 [main] INFO bt.runtime.BtRuntimeBuilder - Auto-loading module bt.tracker.http.HttpTrackerModule with default configuration
20:35:03.916 [main] INFO bt.runtime.BtRuntimeBuilder - Auto-loading module bt.peerexchange.PeerExchangeModule with default configuration
20:35:03.948 [main] DEBUG bt.service.ClasspathApplicationService - Processing manifest file: jar:file:/C:/Users/Snijele/.m2/repository/ch/qos/logback/logback-classic/1.2.3/logback-classic-1.2.3.jar!/META-INF/MANIFEST.MF
20:35:03.949 [main] DEBUG bt.service.ClasspathApplicationService - Bundle-SymbolicName: ch.qos.logback.classic
20:35:03.950 [main] DEBUG bt.service.ClasspathApplicationService - Processing manifest file: jar:file:/C:/Users/Snijele/.m2/repository/ch/qos/logback/logback-core/1.2.3/logback-core-1.2.3.jar!/META-INF/MANIFEST.MF
20:35:03.950 [main] DEBUG bt.service.ClasspathApplicationService - Bundle-SymbolicName: ch.qos.logback.core
20:35:03.950 [main] DEBUG bt.service.ClasspathApplicationService - Processing manifest file: jar:file:/C:/Users/Snijele/.m2/repository/org/slf4j/slf4j-api/1.7.25/slf4j-api-1.7.25.jar!/META-INF/MANIFEST.MF
20:35:03.951 [main] DEBUG bt.service.ClasspathApplicationService - Bundle-SymbolicName: slf4j.api
20:35:03.951 [main] DEBUG bt.service.ClasspathApplicationService - Processing manifest file: jar:file:/C:/Users/Snijele/.m2/repository/com/github/atomashpolskiy/bt-http-tracker-client/1.3.1/bt-http-tracker-client-1.3.1.jar!/META-INF/MANIFEST.MF
20:35:03.951 [main] DEBUG bt.service.ClasspathApplicationService - Bundle-SymbolicName: null
20:35:03.951 [main] DEBUG bt.service.ClasspathApplicationService - Processing manifest file: jar:file:/C:/Users/Snijele/.m2/repository/org/apache/httpcomponents/httpclient/4.5.2/httpclient-4.5.2.jar!/META-INF/MANIFEST.MF
20:35:03.952 [main] DEBUG bt.service.ClasspathApplicationService - Bundle-SymbolicName: null
20:35:03.952 [main] DEBUG bt.service.ClasspathApplicationService - Processing manifest file: jar:file:/C:/Users/Snijele/.m2/repository/commons-codec/commons-codec/1.9/commons-codec-1.9.jar!/META-INF/MANIFEST.MF
20:35:03.953 [main] DEBUG bt.service.ClasspathApplicationService - Bundle-SymbolicName: org.apache.commons.codec
20:35:03.953 [main] DEBUG bt.service.ClasspathApplicationService - Processing manifest file: jar:file:/C:/Users/Snijele/.m2/repository/com/github/atomashpolskiy/bt-core/1.3.1/bt-core-1.3.1.jar!/META-INF/MANIFEST.MF
20:35:03.954 [main] DEBUG bt.service.ClasspathApplicationService - Bundle-SymbolicName: com.github.atomashpolskiy.bt-core
20:35:03.954 [main] DEBUG bt.service.ClasspathApplicationService - Will read version from manifest file: jar:file:/C:/Users/Snijele/.m2/repository/com/github/atomashpolskiy/bt-core/1.3.1/bt-core-1.3.1.jar!/META-INF/MANIFEST.MF
20:35:03.954 [main] DEBUG bt.service.ClasspathApplicationService - Bt version 1.3
20:35:04.063 [bt.service.executor-thread-1] DEBUG bt.processor.ChainProcessor - Processing next stage: torrent ID (2b32e64f6cd755a9e54d60e205a9681d6670cfae), stage (bt.processor.torrent.CreateSessionStage)
20:35:04.066 [bt.service.executor-thread-1] DEBUG bt.torrent.compiler.MessagingAgentCompiler - Compiling messaging agent type: bt.peerexchange.PeerExchangePeerSourceFactory
20:35:04.067 [bt.service.executor-thread-1] DEBUG bt.torrent.compiler.MessagingAgentCompiler - Compiled producer method: produce
20:35:04.067 [bt.service.executor-thread-1] DEBUG bt.torrent.compiler.MessagingAgentCompiler - Compiled consumer method {consumedType=bt.peerexchange.PeerExchange}: consume
20:35:04.067 [bt.service.executor-thread-1] DEBUG bt.torrent.compiler.MessagingAgentCompiler - Compiled consumer method {consumedType=bt.protocol.extended.ExtendedHandshake}: consume
20:35:04.067 [bt.service.executor-thread-1] DEBUG bt.torrent.compiler.MessagingAgentCompiler - Compiled 3 consumer/producer methods
20:35:04.076 [bt.service.executor-thread-1] DEBUG bt.processor.ChainProcessor - Processing next stage: torrent ID (2b32e64f6cd755a9e54d60e205a9681d6670cfae), stage (bt.processor.magnet.FetchMetadataStage)
20:35:04.076 [bt.service.executor-thread-1] DEBUG bt.torrent.compiler.MessagingAgentCompiler - Compiling messaging agent type: bt.torrent.messaging.MetadataConsumer
20:35:04.077 [bt.service.executor-thread-1] DEBUG bt.torrent.compiler.MessagingAgentCompiler - Compiled producer method: produce
20:35:04.077 [bt.service.executor-thread-1] DEBUG bt.torrent.compiler.MessagingAgentCompiler - Compiled consumer method {consumedType=bt.magnet.UtMetadata}: consume
20:35:04.077 [bt.service.executor-thread-1] DEBUG bt.torrent.compiler.MessagingAgentCompiler - Compiled consumer method {consumedType=bt.protocol.extended.ExtendedHandshake}: consume
20:35:04.077 [bt.service.executor-thread-1] DEBUG bt.torrent.compiler.MessagingAgentCompiler - Compiled 3 consumer/producer methods
20:35:04.077 [bt.service.executor-thread-1] DEBUG bt.torrent.compiler.MessagingAgentCompiler - Compiling messaging agent type: bt.torrent.messaging.BitfieldCollectingConsumer
20:35:04.077 [bt.service.executor-thread-1] DEBUG bt.torrent.compiler.MessagingAgentCompiler - Compiled consumer method {consumedType=bt.protocol.Have}: consume
20:35:04.077 [bt.service.executor-thread-1] DEBUG bt.torrent.compiler.MessagingAgentCompiler - Compiled consumer method {consumedType=bt.protocol.Bitfield}: consume
20:35:04.077 [bt.service.executor-thread-1] DEBUG bt.torrent.compiler.MessagingAgentCompiler - Compiled 2 consumer/producer methods

Am I missing something?

Question: Failing UDP trackers: Failed to receive response from the tracker

Hello,
I'm completely new to the bittorrent protocol so I'm probably doing a million things wrong.

The trouble is I can't seem to get any response from UDP trackers. HTTP trackers however work fine.
This has been the case with other libraries that I have tried, so it is likely there is nothing wrong with the implementation. Any ideas how to solve this?

Thanks,
Raudius

bt.BtException: Failed to receive response from the tracker
	at bt.tracker.udp.UdpMessageWorker.sendMessage(UdpMessageWorker.java:80)
	at bt.tracker.udp.UdpMessageWorker.sendMessage(UdpMessageWorker.java:82)
	at bt.tracker.udp.UdpMessageWorker.createSession(UdpMessageWorker.java:67)
	at bt.tracker.udp.UdpMessageWorker.getSession(UdpMessageWorker.java:61)
	at bt.tracker.udp.UdpMessageWorker.sendMessage(UdpMessageWorker.java:56)
	at bt.tracker.udp.UdpTracker$1.announceEvent(UdpTracker.java:109)
	at bt.tracker.udp.UdpTracker$1.start(UdpTracker.java:81)
	at bt.tracker.MultiTracker$1.lambda$0(MultiTracker.java:61)
	at bt.tracker.MultiTracker$1.tryForAllTrackers(MultiTracker.java:111)
	at bt.tracker.MultiTracker$1.start(MultiTracker.java:61)
	at bt.torrent.DefaultTorrentDescriptor.start(DefaultTorrentDescriptor.java:44)
	at bt.DefaultClient.doStart(DefaultClient.java:76)
	at bt.DefaultClient.startAsync(DefaultClient.java:70)
	at bt.RuntimeAwareClient.startAsync(RuntimeAwareClient.java:30)
	at bt.LazyClient.startAsync(LazyClient.java:39)
	at com.canariapp.flixseek.torrentget.TorrentManager.addTorrent(TorrentManager.java:34)
	at com.canariapp.flixseek.torrentget.TorrentManager.main(TorrentManager.java:65)
Caused by: java.util.concurrent.TimeoutException
	at java.util.concurrent.CompletableFuture.timedGet(CompletableFuture.java:1771)
	at java.util.concurrent.CompletableFuture.get(CompletableFuture.java:1915)
	at bt.tracker.udp.UdpMessageWorker.sendMessage(UdpMessageWorker.java:75)
	... 16 more

Partial download for a multi-file torrent

Depends on #11.

One corner case to keep in mind is when torrent data is not perfectly aligned with the size of a piece. In such case some unwanted files might be created on the disk. I wonder if these leftovers might simply be deleted as soon as the download is complete -- this is going to affect the bitfield, as some pieces will be only partially available. Currently Bt client will consider these pieces to be "missing" and will attempt to re-download them.

Use WeakMap/WeakReferences instead of Peer objects for caching

There are quite a few places where some peer-related artifacts are cached in the form of a Map with the key being the Peer object itself. These artifacts accumulate over time even for peers that the client is no longer connected to, making it a potential memory leak.

In-memory storage with streaming output

In-memory storage by itself might be useful in a number of scenarios:

  • small or temporary files, like a textual readme, that the user wants to preview but does not want to save to disk
  • filesystem is not available, or the user does not have a write access
  • some kind of "maximum performance" mode
    etc.

All of this might be useful, but the real killer feature would be an optional "streaming" mode of operation. In this mode the storage would simply re-route the incoming data to a binary output stream. Of course, this mode will only make sense, when the sequential piece selector is used, and will require accumulating and re-ordering the arriving blocks under the hood.

One possible usage scenario would be to add an option for CLI client to stream the torrent data to stdout. Then this data can be piped to any other process, e.g. for large textual files it might be less, tail or grep. For video/audio it will be a media player that supports live stream decoding.

Jar Bt

Hi, where can i download the jar file to put in my project to use your library? Thanks.

Non-static torrents

Good day,

Not too sure what this is called but seeing as you have read the specifications for these protocols I'm sure you'll be able to tell.

May I ask if you have support for changing torrents? I'm sure there's a proper name for that. There's an app that uses torrent protocol to sync folders. I was thinking about this and I thought that maybe it changes the torrents contents and keep downloading them. Does bt support this?

Integration tests for HTTP/UDP trackers

Currently there are no integration tests for interaction with trackers, only unit tests. Need to investigate, what are the existing free tracker implementations, preferably written in Java and available in Maven Central, and if it would be possible to make use of any of those in ITs.

Switch integration tests to using in-memory storage

Per #21 it's now possible to create a FileSystemStorage with a java.nio.files.Path. Next logical step is to leverage this new feature in ITs, more specifically in bt.it.fixture.BaseBtTest and other related classes in bt.it.fixture, by using an in-memory storage, that supports java.nio.files API, e.g Jimfs, which was mentioned in #21.

The condition of unreachability of the peer does not check the connection for success

if (acquiredConnection == null || throwable != null) {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Peer is unreachable: {}. Will prevent further attempts to establish connection.", peer);
}
unreachablePeers.putIfAbsent(peer, System.currentTimeMillis());
}

if (throwable != null || acquiredConnection == null || !acquiredConnection.isSuccess()) {

How to use the Infohash to get the torrent file ?

I'm working the Bt a few weeks , but i have been stumped how to use the infohash to get connection with peer and download torrent file T_T . when i send a query to ask for more piece , the peer is not response for that , but other request is response correct such as handshake .

Could you show me how to do this?

Thank you .

Having problem seeding a completed file.

Hi,

I'm trying to seed a file which has been downloaded successfully. The tracker registers that the client has the whole file, but when I try to download the file using another client, the client says the tracker has no seeders.

But when I switch the clients, the BT client does download from the seeder.

Any ideas?

Thanks

Can't connect to peers

I used the instance code, even the magnet link is the same (I tried to use my own), but nothing happens

public static void main(String[] args) {
        Config config = new Config() {
            @Override
            public int getNumOfHashingThreads() {
                return Runtime.getRuntime().availableProcessors() * 2;
            }
        };

        // enable bootstrapping from public routers
        Module dhtModule = new DHTModule(new DHTConfig() {
            @Override
            public boolean shouldUseRouterBootstrap() {
                return true;
            }
        });

        // get download directory
        Path targetDirectory = new File("~/Downloads").toPath();

        // create file system based backend for torrent data
        Storage storage = new FileSystemStorage(targetDirectory);

        // create client with a private runtime
        BtClient client = Bt.client()
                .config(config)
                .storage(storage)
                .magnet("magnet:?xt=urn:btih:af0d9aa01a9ae123a73802cfa58ccaf355eb19f1")
                .autoLoadModules()
                .module(dhtModule)
                .stopWhenDownloaded()
                .build();

        // launch
        client.startAsync().join();
    }

The conclusion showed 3 lines and it all ended

309 [main] INFO bt.runtime.BtRuntimeBuilder - Auto-loading module bt.tracker.http.HttpTrackerModule with default configuration
309 [main] INFO bt.runtime.BtRuntimeBuilder - Auto-loading module bt.peerexchange.PeerExchangeModule with default configuration
318 [main] INFO bt.runtime.BtRuntimeBuilder - Overriding auto-loaded module bt.dht.DHTModule
2482 [bt.net.pool.incoming-acceptor] INFO bt.net.PeerConnectionPool - Opening server channel for incoming connections @ /192.168.1.34:6891

What do I need to do to get it to work?

JDK 9 Compatibility

This project is participating in JDK 9 Quality Outreach program, so I encourage both users and developers to devote some time and test Bt under newest Java 9.

Recent JDK 9 builds can be downloaded here: http://jdk.java.net/9/

Please, report issues and bugs in this thread and via http://bugreport.java.com/ (in the latter case please post here a link to the submitted issue)

Use the following command to build with compiler's language level set to Java 9:
mvn clean install -Pjdk9

Buffer for writable blocks

Currently blocks are written to disk immediately in the same order that they arrive from peers (which in most cases is random). Quite obviously, this behaves poorly on storage devices with non-random access. We should implement an intermediate in-memory buffer of configurable size to hold the arriving blocks until a piece (or a number of pieces) is complete. When the piece(-s) is complete, it can be verified and written to disk. This will eliminate a big number of disk seeks, esp. if adjacent pieces are flushed to disk in one batch, and also the reads that are made during piece verification.

Support for Java 7 and older

I'm trying to create a client app for this lib but it uses functions available only in java 8 and cannot run the app on pre android N since java 8 functions are only available for android N.

Private Tracker - Unsupported/inactive torrent requested

I am trying to download a torrent with private tracker. I'm getting this error on bt-cli:

Exception in thread "bt.net.pool.connection-worker-4" java.lang.IllegalStateException: Unsupported/inactive torrent requested
        at bt.net.MSEHandshakeProcessor.negotiateIncoming(MSEHandshakeProcessor.java:361)
        at bt.net.PeerConnectionFactory.createConnection(PeerConnectionFactory.java:73)
        at bt.net.PeerConnectionFactory.createIncomingConnection(PeerConnectionFactory.java:57)
        at bt.net.PeerConnectionPool.lambda$acceptIncomingConnection$63(PeerConnectionPool.java:347)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
        at java.lang.Thread.run(Unknown Source)

The file bt.log has:
WARN DefaultTorrentDescriptor: Tracker URL protocol is not supported: https://..tracker../announce.php?passkey=XXXX

What could be happening?
Thanks

Support for file selection (aka partial downloads)

I've just added the support for partial downloads in master, so it goes into 1.7 release. There are a few issues remaining to be solved and things to be done:

  • I've noticed that sometimes CLI does not terminate when all non-skipped files have been downloaded. This had never happened before, so I tend to think that I've introduced a bug somewhere. Need to investigate (might start with bt.processor.torrent.ProcessTorrentStage#doExecute, which controls when download is considered finished). Maybe it's a CLI-specific issue (it's hard to say b/c there aren't any integration tests for partial downloads yet).
  • Adding a couple of unit tests for new methods in bt.data.Bitfield would be nice
  • CLI client might need an additional command-line flag to disable file selection (otherwise people may be forced to keep Enter/Esc pressed for quite some time if there are many files in the torrent)
  • Displaying selection prompt for an existing file (e.g. when it's not the first session for current torrent) makes little sense
  • Esc keypress does not work in headless mode
  • Ctrl-C keypress does not work in file selection dialog when run with GUI
  • Might want to update the gif in the README to show off the new feature (looks pretty cool!)

Support for BEP-5: DHT Protocol

I am a newbie coder. I was planning to implement BitTorrent protocol. It's like some magic for me. But I decided to checkout libraries first, and many of the libraries said in docs that they don't have DHT support and ones which did were messy.

But to check out the performance, I am gonna try out all of them, of course including bt. I was just wondering if you have plans to implement the BPE-5, the DHT, so that I can use it in the future. Or, if I have some confidence, I think I will look into your code and think about implementing DHT and contributing to bt, though it's not an easy task for a developer like me..

Documentation on getting a PeerConnection instance?

I've been looking through your code at everything related to direct connections to peers, but am having trouble piecing it together. I'm not using your library for BitTorrent per se, but am trying to look up peers in DHT by their ID and make a socket connection to them.

Ideally I'll stumble on code like the following:

CompletableFuture<PeerConnection> peerFut = runtime.getPeerconnectionById(peerID);
peerFut.get().postMessage(new Message("Hello"));

Is there any documentation or particular area of the source that you could point me to on establishing peer connections? I'd rather not re-write all of the hard work done by you and others required to punch holes in firewalls, etc.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.