dtorrent_common

A common library for Dart torrent client development. This package provides utilities and classes commonly used in BitTorrent client implementations.

codecov

Features

  • CompactAddress: Efficient encoding/decoding of IP addresses and ports in compact format (IPv4 and IPv6)
  • Utility Functions: Random byte generation, hex encoding, and more
  • Extension Methods: Convenient hex string conversion for integers and iterables
  • Public Tracker Discovery: Fetch public BitTorrent tracker URLs from multiple sources

Installation

Add dtorrent_common to your pubspec.yaml:

dependencies:
  dtorrent_common: ^1.0.8

Then run:

dart pub get

Usage

CompactAddress

CompactAddress represents an IP address and port in compact format, which is commonly used in BitTorrent protocols.

Creating a CompactAddress

import 'dart:io';
import 'package:dtorrent_common/dtorrent_common.dart';

// Create from IP address and port
final address = CompactAddress(
  InternetAddress('192.168.1.1'),
  6881,
);

// Create IPv6 address
final ipv6Address = CompactAddress(
  InternetAddress('2001:0db8:85a3:0000:0000:8a2e:0370:7334'),
  6881,
);

Converting to Bytes

// Convert to compact format bytes
final bytes = address.toBytes(); // [192, 168, 1, 1, 26, 225]

// Get fixed-length Uint8List
final fixedBytes = address.toBytes(false);

Parsing from Bytes

// Parse a single IPv4 address (requires 6 bytes)
final parsed = CompactAddress.parseIPv4Address(bytes);
print(parsed); // 192.168.1.1:6881

// Parse multiple IPv4 addresses
final multipleBytes = [192, 168, 1, 1, 26, 225, 192, 168, 1, 2, 26, 226];
final addresses = CompactAddress.parseIPv4Addresses(multipleBytes);

// Parse IPv6 addresses (requires 18 bytes per address)
final ipv6Parsed = CompactAddress.parseIPv6Address(ipv6Bytes);
final ipv6Addresses = CompactAddress.parseIPv6Addresses(ipv6Bytes);

Working with Multiple Addresses

final addresses = [
  CompactAddress(InternetAddress('127.0.0.1'), 6881),
  CompactAddress(InternetAddress('127.0.0.2'), 6882),
];

// Convert multiple addresses to bytes
final allBytes = CompactAddress.multipleAddressBytes(addresses);

// Parse them back
final parsed = CompactAddress.parseIPv4Addresses(allBytes);

Contact Encoding

// Convert to contact encoding string (used in some BitTorrent protocols)
final contactStr = address.toContactEncodingString();

Utility Functions

Random Bytes

// Generate random bytes (returns List<int>)
final random = randomBytes(20);

// Generate random bytes as Uint8List
final typedRandom = randomBytes(20, true);

Random Integer

// Generate random integer in range [0, max)
final value = randomInt(100); // Returns 0-99

Hex String Conversion

// Convert buffer to hexadecimal string
final hex = transformBufferToHexString([1, 15, 255]);
print(hex); // '010fff'

Extension Methods

Integer to Hex String

import 'package:dtorrent_common/dtorrent_common.dart';

final hex1 = 0.toHexString();   // '00'
final hex2 = 15.toHexString();  // '0f'
final hex3 = 255.toHexString(); // 'ff'

Iterable to Hex String

// Convert iterable of integers to hex string
final hex = [1, 2, 255].toHexString();
print(hex); // '0102ff'

// With separator
final hexWithSep = [1, 2, 255].toHexString(separator: ':');
print(hexWithSep); // '01:02:ff'

// Custom empty value
final emptyHex = <int>[].toHexString(empty: 'none');
print(emptyHex); // 'none'

Finding Public Trackers

// Fetch public tracker URLs from multiple sources
findPublicTrackers().listen((trackers) {
  print('Found ${trackers.length} trackers from source');
  for (final tracker in trackers) {
    print('  - $tracker');
  }
});

The function queries multiple public tracker sources:

  • newtrackon.com
  • trackerslist.com
  • ngosang/trackerslist (via jsDelivr CDN)
  • at.raxianch.moe

API Reference

CompactAddress

  • Constructor: CompactAddress(InternetAddress address, int port)
  • toBytes(bool growable = true): Converts to compact format bytes
  • clone(): Creates a copy of the address
  • toContactEncodingString(): Converts to contact encoding string
  • parseIPv4Address(List: Parses single IPv4 address
  • parseIPv4Addresses(List: Parses multiple IPv4 addresses
  • parseIPv6Address(List: Parses single IPv6 address
  • parseIPv6Addresses(List: Parses multiple IPv6 addresses
  • multipleAddressBytes(List: Converts multiple addresses to bytes

Utility Functions

  • randomBytes(int count, bool typedList = false): Generates random bytes
  • randomInt(int max): Generates random integer in range [0, max)
  • transformBufferToHexString(List: Converts buffer to hex string
  • findPublicTrackers(): Returns Stream<List

Extension Methods

  • int.toHexString(): Converts integer to two-digit hex string
  • Iterable: Converts iterable to hex string

Compact Format Details

The compact format is used in BitTorrent protocol to efficiently encode IP addresses and ports:

  • IPv4: 6 bytes total (4 bytes for IP + 2 bytes for port in big-endian)
  • IPv6: 18 bytes total (16 bytes for IP + 2 bytes for port in big-endian)

Example IPv4 encoding:

IP: 192.168.1.1 → [192, 168, 1, 1]
Port: 6881 → [26, 225] (0x1A 0xE1 in big-endian)
Result: [192, 168, 1, 1, 26, 225]

Testing

Run tests:

dart test

Run tests with coverage:

dart test --coverage=coverage
dart run coverage:format_coverage --lcov --in=coverage --out=coverage/lcov.info --packages=.dart_tool/package_config.json --report-on=lib

Or use the provided script:

dart tool/coverage.dart

The coverage report will be generated at coverage/lcov.info and can be viewed with tools like genhtml or uploaded to services like Codecov.

Coverage is automatically uploaded to Codecov on every push and pull request via GitHub Actions.

Libraries

dtorrent_common
A common library for Dart torrent client development.