Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,7 @@
- Change congestion control

## 0.3.0
- Add Send Metadata extension (BEP0009)
- Add Send Metadata extension (BEP0009)

## 0.3.1
- nullsafety
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@
Dart library for implementing BitTorrent client.

Whole Dart Torrent client contains serival parts :
- [Bencode](https://pub.dev/packages/bencode_dart)
- [Bencode](https://pub.dev/packages/b_encode_decode)
- [Tracker](https://pub.dev/packages/torrent_tracker)
- [DHT](https://pub.dev/packages/dht_dart)
- [Torrent model](https://pub.dev/packages/torrent_model)
- [Common library](https://pub.dev/packages/dartorrent_common)
- [Torrent model](https://pub.dev/packages/dtorrent_parser)
- [Common library](https://pub.dev/packages/dtorrent_common)
- [UTP](https://pub.dev/packages/utp)

This package implements regular BitTorrent Protocol and manage above packages to work together for downloading.
Expand All @@ -29,10 +29,10 @@ Other support will come soon.

## How to use

This package need to dependency [`torrent_model`](https://pub.dev/packages/torrent_model):
This package need to dependency [`dtorrent_parser`](https://pub.dev/packages/dtorrent_parser):
```
dependencies:
torrent_model : ^1.0.3
dtorrent_parser : ^1.0.4
torrent_task : '>= 0.2.1 < 2.0.0'
```

Expand Down
29 changes: 22 additions & 7 deletions analysis_options.yaml
Original file line number Diff line number Diff line change
@@ -1,14 +1,29 @@
# Defines a default set of lint rules enforced for
# projects at Google. For details and rationale,
# see https://github.com/dart-lang/pedantic#enabled-lints.
include: package:pedantic/analysis_options.yaml
# This file configures the static analysis results for your project (errors,
# warnings, and lints).
#
# This enables the 'recommended' set of lints from `package:lints`.
# This set helps identify many issues that may lead to problems when running
# or consuming Dart code, and enforces writing Dart using a single, idiomatic
# style and format.
#
# If you want a smaller set of lints you can change this to specify
# 'package:lints/core.yaml'. These are just the most critical lints
# (the recommended set includes the core lints).
# The core lints are also what is used by pub.dev for scoring packages.

include: package:lints/recommended.yaml
# Uncomment the following section to specify additional rules.

# For lint rules and documentation, see http://dart-lang.github.io/linter/lints.
# Uncomment to specify additional rules.
# linter:
# rules:
# - camel_case_types

analyzer:
# analyzer:
# exclude:
# - path/to/excluded/files/**

# For more information about the core and recommended set of lints, see
# https://dart.dev/go/core-lints

# For additional information about configuring this file, see
# https://dart.dev/guides/language/analysis-options
10 changes: 4 additions & 6 deletions example/lsd_example.dart
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
import 'dart:io';

import 'package:torrent_model/torrent_model.dart';
import 'package:torrent_task/src/lsd/lsd.dart';
import 'package:torrent_task/torrent_task.dart';
import 'package:dtorrent_parser/dtorrent_parser.dart';
import 'package:dtorrent_task/src/lsd/lsd.dart';
import 'package:dtorrent_task/dtorrent_task.dart';

void main(List<String> args) async {
print(await getTorrenTaskVersion());
exit(1);
var torrentFile = 'example/12.torrent';
var savePath = 'g:/bttest';
var torrentFile = 'example${Platform.pathSeparator}test4.torrent';
var model = await Torrent.parse(torrentFile);
var infoHash = model.infoHash;
var lsd = LSD(infoHash, 'daa231dfa');
Expand Down
63 changes: 51 additions & 12 deletions example/metadata_example.dart
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
import 'dart:async';
import 'dart:typed_data';

import 'package:bencode_dart/bencode_dart.dart';
import 'package:dartorrent_common/dartorrent_common.dart';
import 'package:torrent_task/src/metadata/metadata_downloader.dart';
import 'package:torrent_tracker/torrent_tracker.dart';
import 'package:b_encode_decode/b_encode_decode.dart';
import 'package:dtorrent_common/dtorrent_common.dart';
import 'package:dtorrent_parser/dtorrent_parser.dart';
import 'package:dtorrent_task/src/metadata/metadata_downloader.dart';
import 'package:dtorrent_task/dtorrent_task.dart';
import 'package:dtorrent_tracker/dtorrent_tracker.dart';

void main(List<String> args) async {
var infohashString = '217bddb5816f2abc56ce1d9fe430711542b109cc';
Expand All @@ -15,25 +18,61 @@ void main(List<String> args) async {
var tracker = TorrentAnnounceTracker(metadata);

// When metadata contents download complete , it will send this event and stop itself:
metadata.onDownloadComplete((data) {
metadata.onDownloadComplete((data) async {
tracker.stop(true);
var msg = decode(Uint8List.fromList(data));
print('complete , info : $msg');
tracker?.stop(true);
Map<String, dynamic> torrent = {};
torrent['info'] = msg;
var torrentModel = parseTorrentFileContent(torrent);
if (torrentModel != null) {
print('complete , info : ${torrentModel.name}');
var startTime = DateTime.now().millisecondsSinceEpoch;
var task = TorrentTask.newTask(torrentModel, 'tmp');
Timer? timer;
task.onTaskComplete(() {
print(
'Complete! spend time : ${((DateTime.now().millisecondsSinceEpoch - startTime) / 60000).toStringAsFixed(2)} minutes');
timer?.cancel();
task.stop();
});
task.onStop(() async {
print('Task Stopped');
});
timer = Timer.periodic(Duration(seconds: 2), (timer) async {
var progress = '${(task.progress * 100).toStringAsFixed(2)}%';
var ads =
((task.averageDownloadSpeed) * 1000 / 1024).toStringAsFixed(2);
var aps = ((task.averageUploadSpeed) * 1000 / 1024).toStringAsFixed(2);
var ds = ((task.currentDownloadSpeed) * 1000 / 1024).toStringAsFixed(2);
var ps = ((task.uploadSpeed) * 1000 / 1024).toStringAsFixed(2);

var utpd = ((task.utpDownloadSpeed) * 1000 / 1024).toStringAsFixed(2);
var utpu = ((task.utpUploadSpeed) * 1000 / 1024).toStringAsFixed(2);
var utpc = task.utpPeerCount;

var active = task.connectedPeersNumber;
var seeders = task.seederNumber;
var all = task.allPeersNumber;
print(
'Progress : $progress , Peers:($active/$seeders/$all)($utpc) . Download speed : ($utpd)($ads/$ds)kb/s , upload speed : ($utpu)($aps/$ps)kb/s');
});
await task.start();
}
});

var u8List = Uint8List.fromList(metadata.infoHashBuffer);

tracker.onPeerEvent((source, event) {
if (event == null) return;
var peers = event.peers;
peers.forEach((element) {
metadata.addNewPeerAddress(element);
});
for (var element in peers) {
metadata.addNewPeerAddress(element, PeerSource.tracker);
}
});
// ignore: unawaited_futures
findPublicTrackers().listen((alist) {
alist.forEach((element) {
for (var element in alist) {
tracker.runTracker(element, u8List);
});
}
});
}
25 changes: 13 additions & 12 deletions example/torrent_task_comin_example.dart
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
import 'dart:async';
import 'dart:io';

import 'package:dartorrent_common/dartorrent_common.dart';
import 'package:torrent_model/torrent_model.dart';
import 'package:torrent_task/torrent_task.dart';
import 'package:dtorrent_common/dtorrent_common.dart';
import 'package:dtorrent_parser/dtorrent_parser.dart';
import 'package:dtorrent_task/dtorrent_task.dart';

/// This example is for connect local
Future<void> main() async {
var model = await Torrent.parse('example/test8.torrent');
// 不获取peers
var model =
await Torrent.parse('example${Platform.pathSeparator}test4.torrent');
// No peers retrieval
model.announces.clear();
var task = TorrentTask.newTask(model, 'g:/bttest5/');
Timer timer;
Timer timer1;
var task = TorrentTask.newTask(model, 'tmp${Platform.pathSeparator}test');
Timer? timer;
Timer? timer1;
task.onFileComplete((filepath) {
print('$filepath downloaded complete');
});
Expand All @@ -31,7 +32,7 @@ Future<void> main() async {
timer = Timer.periodic(Duration(seconds: 2), (timer) {
try {
print(
'Downloaed: ${task.downloaded / (1024 * 1024)} mb , ${((task.downloaded / model.length) * 100).toStringAsFixed(2)}%');
'Downloaed: ${task.downloaded ?? 0 / (1024 * 1024)} mb , ${((task.downloaded ?? 0 / model.length) * 100).toStringAsFixed(2)}%');
} finally {}
});

Expand All @@ -50,7 +51,7 @@ Future<void> main() async {
// await Future.delayed(Duration(seconds: 120));
// task.resume();
// });
// 自己下载自己
task.addPeer(CompactAddress(InternetAddress.tryParse('192.168.0.24'), 57331),
PeerType.UTP);
// download from yourself
task.addPeer(CompactAddress(InternetAddress.tryParse('192.168.0.24')!, 57331),
PeerSource.manual);
}
42 changes: 20 additions & 22 deletions example/torrent_task_example.dart
Original file line number Diff line number Diff line change
@@ -1,19 +1,20 @@
import 'dart:async';
import 'dart:developer';
import 'dart:io';

import 'package:dartorrent_common/dartorrent_common.dart';
import 'package:torrent_model/torrent_model.dart';
import 'package:torrent_task/torrent_task.dart';
import 'package:dtorrent_common/dtorrent_common.dart';
import 'package:dtorrent_parser/dtorrent_parser.dart';
import 'package:dtorrent_task/dtorrent_task.dart';

void main() async {
try {
var torrentFile = 'example/test4.torrent';
var savePath = 'g:/bttest';
var torrentFile = 'example${Platform.pathSeparator}test4.torrent';
var savePath = 'tmp${Platform.pathSeparator}test';
var model = await Torrent.parse(torrentFile);
// model.announces.clear();
var task = TorrentTask.newTask(model, savePath);
Timer timer;
Timer timer1;
Timer? timer;
Timer? timer1;
var startTime = DateTime.now().millisecondsSinceEpoch;
task.onTaskComplete(() {
print(
Expand All @@ -29,29 +30,26 @@ void main() async {

// ignore: unawaited_futures
findPublicTrackers().listen((alist) {
alist.forEach((element) {
for (var element in alist) {
task.startAnnounceUrl(element, model.infoHashBuffer);
});
}
});

model.nodes?.forEach((element) {
log('Adding dht nodes');
for (var element in model.nodes) {
log('dht node $element');
task.addDHTNode(element);
});
}
print(map);

timer = Timer.periodic(Duration(seconds: 2), (timer) async {
var progress = '${(task.progress * 100).toStringAsFixed(2)}%';
var ads =
'${((task.averageDownloadSpeed) * 1000 / 1024).toStringAsFixed(2)}';
var aps =
'${((task.averageUploadSpeed) * 1000 / 1024).toStringAsFixed(2)}';
var ds =
'${((task.currentDownloadSpeed) * 1000 / 1024).toStringAsFixed(2)}';
var ps = '${((task.uploadSpeed) * 1000 / 1024).toStringAsFixed(2)}';
var ads = ((task.averageDownloadSpeed) * 1000 / 1024).toStringAsFixed(2);
var aps = ((task.averageUploadSpeed) * 1000 / 1024).toStringAsFixed(2);
var ds = ((task.currentDownloadSpeed) * 1000 / 1024).toStringAsFixed(2);
var ps = ((task.uploadSpeed) * 1000 / 1024).toStringAsFixed(2);

var utpd =
'${((task.utpDownloadSpeed) * 1000 / 1024).toStringAsFixed(2)}';
var utpu = '${((task.utpUploadSpeed) * 1000 / 1024).toStringAsFixed(2)}';
var utpd = ((task.utpDownloadSpeed) * 1000 / 1024).toStringAsFixed(2);
var utpu = ((task.utpUploadSpeed) * 1000 / 1024).toStringAsFixed(2);
var utpc = task.utpPeerCount;

var active = task.connectedPeersNumber;
Expand Down
8 changes: 4 additions & 4 deletions lib/torrent_task.dart → lib/dtorrent_task.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
library torrent_task;
library dtorrent_task;

import 'dart:io';

Expand All @@ -7,11 +7,11 @@ export 'src/file/file_base.dart';
export 'src/piece/piece_base.dart';
export 'src/peer/peer_base.dart';

/// Peer ID前缀
/// Peer ID prefix
const ID_PREFIX = '-DT0201-';

/// 当前版本号
Future<String> getTorrenTaskVersion() async {
/// Current version number
Future<String?> getTorrenTaskVersion() async {
var file = File('pubspec.yaml');
if (await file.exists()) {
var lines = await file.readAsLines();
Expand Down
Loading