Bt   java bittorrent done right

Release 1.5

Release 1.5 was published to Maven Central on September 26th, 2017. There are several cool features in this release.

Runtime events

The new centralized mechanism for publishing/receiving events is represented by two DI services: bt.event.EventSink for publishing and bt.event.EventSource for subscriptions. Library users have an easy access to the EventSource instance via bt.runtime.BtRuntime#getEventSource().

Currently there are the following types of events:

  • when a new peer has been discovered for some torrent;
  • when a new connection with some peer has been established;
  • when a connection with some peer has been terminated;
  • when local information about some peer’s data has been updated (received BITFIELD or HAVE message);
  • when processing of some torrent has begun;
  • when processing of some torrent has finished;

Torrent processing listeners

This is mostly an internal enhancement, but it brings two useful features for library users:

1) Ability to stop torrent processing as soon as the metadata has been fetched. It can be convenient, when one is using magnet links and doesn’t want to download the actual data, but just the info dictionary. See bt.TorrentClientBuilder#afterTorrentFetched.

2) Ability to stop torrent processing as soon as the data has been downloaded. It is supposed to replace the custom listeners, that periodically perform state.getPiecesRemaining() == 0 checks and then invoke client.stop(). The new alternative is much more efficient, because it does not use a separate thread. See bt.TorrentClientBuilder#stopWhenDownloaded.

I/O selector

Leveraging OS I/O multiplexing allowed to significantly reduce the number of system calls and slightly cut down on the CPU usage in message dispatching loop.

Module extenders

This feature is borrowed from Bootique project (which I strongly recommend to anyone, who is interested in runnable Java applications). It replaces contribution methods with a clearer and more concise API for contributing custom extensions into the core. Instead of invoking individual contributions methods, downstream modules should now call bt.module.ServiceModule#extend(Binder) or bt.module.ProtocolModule#extend(Binder) and use methods in the returned builder instance, e.g.:

import com.google.inject.Binder;
import com.google.inject.Module;

import bt.module.ProtocolModule;

public class MyModule implements Module {
    
    @Override
    public void configure(Binder binder) {
        ProtocolModule.extend(binder)
            .addMessageHandler(20, ExtendedProtocol.class)
            .addExtendedMessageHandler("ut_metadata", UtMetadataMessageHandler.class);
    }
}

…and more

As usual, here’s the complete list of what has been done:

Changes/New Features:

  • Introduce a unified, centralized mechanism for publishing/receiving events
  • Introduce a processing stage listener mechanism

Bug Fixes/Improvements:

  • Disallow to set client’s runtime other than via Bt factory method
  • Introduce module extenders for contributing custom extensions
  • Disable BEP-9 metadata exchange for private torrents
  • DefaultClient state fix when client is stopped PR#37
  • Announce stats to tracker on start, stop, complete
  • Use I/O selector for receiving incoming messages
  • Allow to override the number of peers to request from a tracker
  • Provide information on creation date and creator of the torrent
  • Support empty files