bun-torrent 0.0.6 → 0.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (114) hide show
  1. package/README.md +48 -5
  2. package/dist/app.d.ts +2 -0
  3. package/dist/app.js +136 -0
  4. package/dist/app.js.map +1 -0
  5. package/dist/client.d.ts +14 -0
  6. package/dist/client.error.d.ts +1 -0
  7. package/dist/client.error.js +1 -0
  8. package/dist/client.error.js.map +1 -1
  9. package/dist/client.js +55 -3
  10. package/dist/client.js.map +1 -1
  11. package/dist/configs/defaults.d.ts +16 -0
  12. package/dist/configs/defaults.js +11 -0
  13. package/dist/configs/defaults.js.map +1 -1
  14. package/dist/dht/DhtClient.d.ts +52 -0
  15. package/dist/dht/DhtClient.js +279 -0
  16. package/dist/dht/DhtClient.js.map +1 -0
  17. package/dist/dht/KBucket.d.ts +12 -0
  18. package/dist/dht/KBucket.js +43 -0
  19. package/dist/dht/KBucket.js.map +1 -0
  20. package/dist/dht/RoutingTable.d.ts +19 -0
  21. package/dist/dht/RoutingTable.js +75 -0
  22. package/dist/dht/RoutingTable.js.map +1 -0
  23. package/dist/dht/errors.d.ts +19 -0
  24. package/dist/dht/errors.js +24 -0
  25. package/dist/dht/errors.js.map +1 -0
  26. package/dist/dht/index.d.ts +8 -0
  27. package/dist/dht/index.js +5 -0
  28. package/dist/dht/index.js.map +1 -0
  29. package/dist/dht/krpc/TransactionId.d.ts +12 -0
  30. package/dist/dht/krpc/TransactionId.js +23 -0
  31. package/dist/dht/krpc/TransactionId.js.map +1 -0
  32. package/dist/dht/krpc/index.d.ts +5 -0
  33. package/dist/dht/krpc/index.js +4 -0
  34. package/dist/dht/krpc/index.js.map +1 -0
  35. package/dist/dht/krpc/messages.d.ts +3 -0
  36. package/dist/dht/krpc/messages.js +163 -0
  37. package/dist/dht/krpc/messages.js.map +1 -0
  38. package/dist/dht/krpc/types.d.ts +54 -0
  39. package/dist/dht/krpc/types.js +14 -0
  40. package/dist/dht/krpc/types.js.map +1 -0
  41. package/dist/dht/routing-table.d.ts +2 -0
  42. package/dist/dht/routing-table.js +2 -0
  43. package/dist/dht/routing-table.js.map +1 -0
  44. package/dist/dht/utils/compact.d.ts +17 -0
  45. package/dist/dht/utils/compact.js +81 -0
  46. package/dist/dht/utils/compact.js.map +1 -0
  47. package/dist/dht/utils/distance.d.ts +5 -0
  48. package/dist/dht/utils/distance.js +25 -0
  49. package/dist/dht/utils/distance.js.map +1 -0
  50. package/dist/magnet/parser/errors.d.ts +2 -1
  51. package/dist/magnet/parser/errors.js +3 -1
  52. package/dist/magnet/parser/errors.js.map +1 -1
  53. package/dist/magnet/parser/index.d.ts +10 -2
  54. package/dist/magnet/parser/index.js +53 -22
  55. package/dist/magnet/parser/index.js.map +1 -1
  56. package/dist/peer/PeerPieceAvailability.d.ts +50 -0
  57. package/dist/peer/PeerPieceAvailability.js +71 -0
  58. package/dist/peer/PeerPieceAvailability.js.map +1 -0
  59. package/dist/peer/availability.d.ts +2 -50
  60. package/dist/peer/availability.js +1 -70
  61. package/dist/peer/availability.js.map +1 -1
  62. package/dist/peer/extended/connection.d.ts +3 -1
  63. package/dist/peer/extended/connection.js +20 -4
  64. package/dist/peer/extended/connection.js.map +1 -1
  65. package/dist/peer/extended/errors.d.ts +1 -0
  66. package/dist/peer/extended/errors.js +1 -0
  67. package/dist/peer/extended/errors.js.map +1 -1
  68. package/dist/peer/extended/metadata/MetadataAssembler.d.ts +12 -0
  69. package/dist/peer/extended/metadata/MetadataAssembler.js +44 -0
  70. package/dist/peer/extended/metadata/MetadataAssembler.js.map +1 -0
  71. package/dist/peer/extended/metadata/assembler.d.ts +1 -12
  72. package/dist/peer/extended/metadata/assembler.js +1 -43
  73. package/dist/peer/extended/metadata/assembler.js.map +1 -1
  74. package/dist/peer/extended/metadata/index.d.ts +1 -0
  75. package/dist/peer/extended/metadata/index.js +20 -8
  76. package/dist/peer/extended/metadata/index.js.map +1 -1
  77. package/dist/peer/index.d.ts +2 -2
  78. package/dist/peer/index.js +1 -1
  79. package/dist/peer/index.js.map +1 -1
  80. package/dist/peer/pool/PeerPool.d.ts +65 -0
  81. package/dist/peer/pool/PeerPool.js +206 -0
  82. package/dist/peer/pool/PeerPool.js.map +1 -0
  83. package/dist/peer/pool/index.d.ts +2 -65
  84. package/dist/peer/pool/index.js +1 -205
  85. package/dist/peer/pool/index.js.map +1 -1
  86. package/dist/peer/session/PeerSession.d.ts +35 -0
  87. package/dist/peer/session/PeerSession.js +200 -0
  88. package/dist/peer/session/PeerSession.js.map +1 -0
  89. package/dist/peer/session/index.d.ts +2 -35
  90. package/dist/peer/session/index.js +1 -199
  91. package/dist/peer/session/index.js.map +1 -1
  92. package/dist/torrent/download/DownloadManager.d.ts +85 -0
  93. package/dist/torrent/download/DownloadManager.js +383 -0
  94. package/dist/torrent/download/DownloadManager.js.map +1 -0
  95. package/dist/torrent/download/index.d.ts +2 -2
  96. package/dist/torrent/download/index.js +1 -1
  97. package/dist/torrent/download/index.js.map +1 -1
  98. package/dist/torrent/download/manager.d.ts +2 -85
  99. package/dist/torrent/download/manager.js +1 -382
  100. package/dist/torrent/download/manager.js.map +1 -1
  101. package/dist/torrent/session/Torrent.d.ts +77 -0
  102. package/dist/torrent/session/Torrent.js +126 -0
  103. package/dist/torrent/session/Torrent.js.map +1 -0
  104. package/dist/torrent/session/index.d.ts +2 -77
  105. package/dist/torrent/session/index.js +1 -125
  106. package/dist/torrent/session/index.js.map +1 -1
  107. package/dist/tracker/udp.js +24 -25
  108. package/dist/tracker/udp.js.map +1 -1
  109. package/dist/utils/UdpSocket.d.ts +12 -0
  110. package/dist/utils/UdpSocket.js +31 -0
  111. package/dist/utils/UdpSocket.js.map +1 -0
  112. package/examples/download-torrent.ts +32 -0
  113. package/examples/magnet-dht.ts +32 -0
  114. package/package.json +5 -1
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  A minimal Bun-native BitTorrent download-only client written in TypeScript.
4
4
 
5
- `bun-torrent` can parse `.torrent` files and tracker-backed magnet links, announce to HTTP and UDP trackers, connect to peers, download pieces, validate piece hashes, and write the downloaded files to disk. The public API is intentionally small: create a `Client`, inspect a torrent when you need metadata, then call `download()`.
5
+ `bun-torrent` can parse `.torrent` files and magnet links, announce to HTTP and UDP trackers, discover peers through the BitTorrent DHT, connect to peers, download pieces, validate piece hashes, and write the downloaded files to disk. The public API is intentionally small: create a `Client`, inspect a torrent when you need metadata, then call `download()`.
6
6
 
7
7
  It has no runtime dependencies.
8
8
 
@@ -57,6 +57,17 @@ await torrent.done;
57
57
 
58
58
  `download()` returns a `Torrent` instance and starts the download immediately.
59
59
 
60
+ ## Runnable Example Files
61
+
62
+ Runnable example files are available in `examples/`:
63
+
64
+ ```bash
65
+ bun examples/download-torrent.ts ./example.torrent ./downloads
66
+ bun examples/magnet-dht.ts "magnet:?xt=urn:btih:..." ./downloads
67
+ ```
68
+
69
+ The magnet example works with tracker-backed and trackerless magnets. It uses the default in-memory DHT node and closes the client before exiting.
70
+
60
71
  ## Client Setup
61
72
 
62
73
  ```ts
@@ -78,6 +89,7 @@ const client = new Client({
78
89
 
79
90
  Client options:
80
91
 
92
+ - `dht`: optional DHT peer discovery implementation, or `false` to disable DHT. By default, the client creates an in-memory DHT node.
81
93
  - `outputDirectory`: directory where downloaded files are written. Defaults to `process.cwd()`.
82
94
  - `files`: optional default file selection for downloads.
83
95
  - `targetConnections`: preferred number of connected peers. Defaults to `20`.
@@ -109,9 +121,11 @@ console.log(metadata.files);
109
121
 
110
122
  Torrent file input can be a file path, `Uint8Array`, or `ArrayBuffer`.
111
123
 
124
+ Call `client.close()` when the client should stop accepting work and close active torrents and its DHT socket.
125
+
112
126
  ## Magnet Links
113
127
 
114
- Magnet links are supported when they include at least one HTTP, HTTPS, or UDP tracker through the `tr` parameter. Metadata is fetched from peers with the `ut_metadata` extension before the normal download flow starts.
128
+ Magnet links are supported with or without trackers. If `tr` parameters are present, the client asks those trackers first. If no tracker returns peers, or the magnet is trackerless, the client falls back to DHT peer discovery. Metadata is fetched from peers with the `ut_metadata` extension before the normal download flow starts.
115
129
 
116
130
  ```ts
117
131
  const magnet =
@@ -134,13 +148,42 @@ const torrent = await client.download(
134
148
  await torrent.done;
135
149
  ```
136
150
 
151
+ Trackerless magnets use the same API. Keep the same `Client` instance if you inspect first and download later, because the default DHT node keeps discovered peers in memory for the current process.
152
+
153
+ ```ts
154
+ import { Client } from 'bun-torrent';
155
+
156
+ const client = new Client({
157
+ outputDirectory: './downloads',
158
+ });
159
+
160
+ const magnet = 'magnet:?xt=urn:btih:0123456789abcdef0123456789abcdef01234567';
161
+
162
+ try {
163
+ const metadata = await client.inspect({ magnet });
164
+
165
+ console.log(metadata.name);
166
+ console.log(metadata.files);
167
+
168
+ const torrent = await client.download({ meta: metadata });
169
+
170
+ torrent.on('progress', (progress) => {
171
+ console.log(`${(progress.percent * 100).toFixed(2)}%`, progress.speed);
172
+ });
173
+
174
+ await torrent.done;
175
+ } finally {
176
+ client.close();
177
+ }
178
+ ```
179
+
137
180
  Supported magnet fields:
138
181
 
139
182
  - `xt=urn:btih:<infoHash>`: required. Hex-encoded 40-character info hashes and base32 32-character info hashes are supported.
140
183
  - `dn`: optional display name.
141
- - `tr`: optional tracker URL. Multiple `tr` parameters are supported.
184
+ - `tr`: optional tracker URL. Multiple `tr` parameters are supported, but trackerless magnets can resolve through DHT.
142
185
 
143
- Trackerless magnets are not supported yet because DHT peer discovery is not implemented. A magnet without `tr` currently fails during inspection with a DHT-not-implemented error.
186
+ The default DHT node is in-memory. It keeps a routing table and a short-lived peer cache for the current process, so a magnet `inspect()` can populate peers that a later `download({ meta })` call can reuse on the same `Client` instance. The DHT state is not persisted to disk.
144
187
 
145
188
  ## Download Options
146
189
 
@@ -181,7 +224,7 @@ Download options:
181
224
  - `speedSampleIntervalMs`: override speed sample interval.
182
225
  - `onChangeState`: receives client setup states: `parsing`, `tracking`, `connecting`, `downloading`.
183
226
 
184
- Tracker announce failures are treated as non-fatal. If no tracker responds, the client can still continue with an empty peer list instead of throwing during tracking.
227
+ Tracker announce failures are treated as non-fatal. If trackers are missing or do not return peers, the client falls back to DHT when it is enabled. With DHT disabled, the client can still continue with an empty peer list instead of throwing during tracking when `minConnections` is `0`.
185
228
 
186
229
  ## Selecting Files
187
230
 
package/dist/app.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env bun
2
+ export {};
package/dist/app.js ADDED
@@ -0,0 +1,136 @@
1
+ #!/usr/bin/env bun
2
+ import { bytesToHex } from './utils/buffers';
3
+ import { formatBytes } from './utils/formats';
4
+ import { Client } from './client';
5
+ const summarizeTorrent = (metadata) => ({
6
+ announce: metadata.announce,
7
+ announceList: metadata.announceList,
8
+ infoHash: bytesToHex(metadata.infoHash),
9
+ name: metadata.name,
10
+ pieceLength: metadata.pieceLength,
11
+ piecesTotal: metadata.pieces.length,
12
+ length: metadata.length,
13
+ files: metadata.files.map((file) => ({
14
+ path: file.path.join('/'),
15
+ length: file.length,
16
+ offset: file.offset,
17
+ })),
18
+ filesTotal: metadata.files.length,
19
+ });
20
+ const usage = () => {
21
+ console.error('Usage:');
22
+ console.error(' bunx bun-torrent inspect <file.torrent>');
23
+ console.error(' bunx bun-torrent inspect <magnet-uri>');
24
+ console.error(' bunx bun-torrent inspect < file.torrent');
25
+ console.error(' bunx bun-torrent download <file.torrent|magnet-uri> [output-directory]');
26
+ };
27
+ const inspect = async (input) => {
28
+ const client = new Client();
29
+ try {
30
+ const metadata = input ? await inspectArgument(client, input) : await inspectStdin(client);
31
+ console.log(JSON.stringify(summarizeTorrent(metadata), null, 2));
32
+ }
33
+ finally {
34
+ client.close();
35
+ }
36
+ };
37
+ const resolveInput = (input) => {
38
+ if (input.startsWith('magnet:')) {
39
+ return { magnet: input };
40
+ }
41
+ return { torrentFile: input };
42
+ };
43
+ const inspectArgument = async (client, input) => {
44
+ return await client.inspect(resolveInput(input));
45
+ };
46
+ const inspectStdin = async (client) => {
47
+ const input = new Uint8Array(await Bun.stdin.arrayBuffer());
48
+ if (input.byteLength === 0) {
49
+ throw new Error('Expected torrent file bytes on stdin');
50
+ }
51
+ return await client.inspect({ torrentFile: input });
52
+ };
53
+ const download = async (input, outputDirectory = './downloads') => {
54
+ if (!input) {
55
+ throw new Error('Expected file.torrent or magnet URI');
56
+ }
57
+ const client = new Client({ outputDirectory });
58
+ let state = 'starting';
59
+ let progress = null;
60
+ let stats = null;
61
+ const render = () => renderProgressLine(state, progress, stats);
62
+ try {
63
+ render();
64
+ const torrent = await client.download(resolveInput(input), {
65
+ progressEvents: 'block',
66
+ onChangeState: (nextState) => {
67
+ state = nextState;
68
+ render();
69
+ },
70
+ });
71
+ progress = torrent.progress;
72
+ stats = torrent.stats;
73
+ render();
74
+ torrent.on('progress', (nextProgress) => {
75
+ progress = nextProgress;
76
+ render();
77
+ });
78
+ torrent.on('peer', (nextStats) => {
79
+ stats = nextStats;
80
+ render();
81
+ });
82
+ await torrent.done;
83
+ state = 'completed';
84
+ progress = torrent.progress;
85
+ stats = torrent.stats;
86
+ render();
87
+ process.stdout.write('\nDownload complete\n');
88
+ }
89
+ finally {
90
+ client.close();
91
+ }
92
+ };
93
+ const renderProgressLine = (state, progress, stats) => {
94
+ const bar = progress ? progressBar(progress.percent) : progressBar(0);
95
+ const percent = progress ? `${(progress.percent * 100).toFixed(2).padStart(6)}%` : ' 0.00%';
96
+ const downloaded = progress ? formatBytes(progress.downloadedBytes) : '0.0 B';
97
+ const total = progress ? formatBytes(progress.totalBytes) : '?';
98
+ const speed = progress?.speed ?? '0.0 Bps';
99
+ const pieces = progress
100
+ ? `pieces=${progress.completedPieces}/${progress.totalPieces}`
101
+ : 'pieces=?/?';
102
+ const peers = stats ? `peers=${stats.connections}/${stats.peers}` : 'peers=0/0';
103
+ const line = `${state.padEnd(11)} ${bar} ${percent} ${downloaded}/${total} ${speed} ${pieces} ${peers}`;
104
+ process.stdout.write(`\r${line}\x1b[K`);
105
+ };
106
+ const progressBar = (percent) => {
107
+ const width = 28;
108
+ const normalized = Math.min(1, Math.max(0, percent));
109
+ const filled = Math.round(normalized * width);
110
+ return `[${'#'.repeat(filled)}${'-'.repeat(width - filled)}]`;
111
+ };
112
+ if (import.meta.main) {
113
+ const command = Bun.argv[2];
114
+ const input = Bun.argv[3];
115
+ const outputDirectory = Bun.argv[4];
116
+ try {
117
+ switch (command) {
118
+ case 'inspect':
119
+ await inspect(input);
120
+ break;
121
+ case 'download':
122
+ await download(input, outputDirectory);
123
+ break;
124
+ default:
125
+ usage();
126
+ process.exitCode = 1;
127
+ }
128
+ }
129
+ catch (error) {
130
+ if (command === 'download')
131
+ process.stdout.write('\n');
132
+ console.error(error instanceof Error ? error.message : String(error));
133
+ process.exitCode = 1;
134
+ }
135
+ }
136
+ //# sourceMappingURL=app.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"app.js","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAE9C,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AA4BlC,MAAM,gBAAgB,GAAG,CAAC,QAAyB,EAAkB,EAAE,CAAC,CAAC;IACrE,QAAQ,EAAE,QAAQ,CAAC,QAAQ;IAC3B,YAAY,EAAE,QAAQ,CAAC,YAAY;IACnC,QAAQ,EAAE,UAAU,CAAC,QAAQ,CAAC,QAAQ,CAAC;IACvC,IAAI,EAAE,QAAQ,CAAC,IAAI;IACnB,WAAW,EAAE,QAAQ,CAAC,WAAW;IACjC,WAAW,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM;IACnC,MAAM,EAAE,QAAQ,CAAC,MAAM;IACvB,KAAK,EAAE,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QACjC,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC;QACzB,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,MAAM,EAAE,IAAI,CAAC,MAAM;KACtB,CAAC,CAAC;IACH,UAAU,EAAE,QAAQ,CAAC,KAAK,CAAC,MAAM;CACpC,CAAC,CAAC;AAEH,MAAM,KAAK,GAAG,GAAS,EAAE;IACrB,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IACxB,OAAO,CAAC,KAAK,CAAC,2CAA2C,CAAC,CAAC;IAC3D,OAAO,CAAC,KAAK,CAAC,yCAAyC,CAAC,CAAC;IACzD,OAAO,CAAC,KAAK,CAAC,2CAA2C,CAAC,CAAC;IAC3D,OAAO,CAAC,KAAK,CAAC,0EAA0E,CAAC,CAAC;AAC9F,CAAC,CAAC;AAEF,MAAM,OAAO,GAAG,KAAK,EAAE,KAAc,EAAiB,EAAE;IACpD,MAAM,MAAM,GAAG,IAAI,MAAM,EAAE,CAAC;IAE5B,IAAI,CAAC;QACD,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,CAAC,MAAM,eAAe,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,YAAY,CAAC,MAAM,CAAC,CAAC;QAE3F,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,gBAAgB,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IACrE,CAAC;YAAS,CAAC;QACP,MAAM,CAAC,KAAK,EAAE,CAAC;IACnB,CAAC;AACL,CAAC,CAAC;AAEF,MAAM,YAAY,GAAG,CAAC,KAAa,EAAmB,EAAE;IACpD,IAAI,KAAK,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;QAC9B,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;IAC7B,CAAC;IAED,OAAO,EAAE,WAAW,EAAE,KAAK,EAAE,CAAC;AAClC,CAAC,CAAC;AAEF,MAAM,eAAe,GAAG,KAAK,EAAE,MAAc,EAAE,KAAa,EAA4B,EAAE;IACtF,OAAO,MAAM,MAAM,CAAC,OAAO,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC;AACrD,CAAC,CAAC;AAEF,MAAM,YAAY,GAAG,KAAK,EAAE,MAAc,EAA4B,EAAE;IACpE,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC,CAAC;IAE5D,IAAI,KAAK,CAAC,UAAU,KAAK,CAAC,EAAE,CAAC;QACzB,MAAM,IAAI,KAAK,CAAC,sCAAsC,CAAC,CAAC;IAC5D,CAAC;IAED,OAAO,MAAM,MAAM,CAAC,OAAO,CAAC,EAAE,WAAW,EAAE,KAAK,EAAE,CAAC,CAAC;AACxD,CAAC,CAAC;AAEF,MAAM,QAAQ,GAAG,KAAK,EAAE,KAAc,EAAE,eAAe,GAAG,aAAa,EAAiB,EAAE;IACtF,IAAI,CAAC,KAAK,EAAE,CAAC;QACT,MAAM,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAC;IAC3D,CAAC;IAED,MAAM,MAAM,GAAG,IAAI,MAAM,CAAC,EAAE,eAAe,EAAE,CAAC,CAAC;IAC/C,IAAI,KAAK,GAAG,UAAU,CAAC;IACvB,IAAI,QAAQ,GAA4B,IAAI,CAAC;IAC7C,IAAI,KAAK,GAAwB,IAAI,CAAC;IAEtC,MAAM,MAAM,GAAG,GAAS,EAAE,CAAC,kBAAkB,CAAC,KAAK,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC;IAEtE,IAAI,CAAC;QACD,MAAM,EAAE,CAAC;QACT,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,YAAY,CAAC,KAAK,CAAC,EAAE;YACvD,cAAc,EAAE,OAAO;YACvB,aAAa,EAAE,CAAC,SAAS,EAAE,EAAE;gBACzB,KAAK,GAAG,SAAS,CAAC;gBAClB,MAAM,EAAE,CAAC;YACb,CAAC;SACJ,CAAC,CAAC;QAEH,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC;QAC5B,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC;QACtB,MAAM,EAAE,CAAC;QAET,OAAO,CAAC,EAAE,CAAC,UAAU,EAAE,CAAC,YAAY,EAAE,EAAE;YACpC,QAAQ,GAAG,YAAY,CAAC;YACxB,MAAM,EAAE,CAAC;QACb,CAAC,CAAC,CAAC;QACH,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,SAAS,EAAE,EAAE;YAC7B,KAAK,GAAG,SAAS,CAAC;YAClB,MAAM,EAAE,CAAC;QACb,CAAC,CAAC,CAAC;QAEH,MAAM,OAAO,CAAC,IAAI,CAAC;QACnB,KAAK,GAAG,WAAW,CAAC;QACpB,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC;QAC5B,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC;QACtB,MAAM,EAAE,CAAC;QACT,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,uBAAuB,CAAC,CAAC;IAClD,CAAC;YAAS,CAAC;QACP,MAAM,CAAC,KAAK,EAAE,CAAC;IACnB,CAAC;AACL,CAAC,CAAC;AAEF,MAAM,kBAAkB,GAAG,CACvB,KAAa,EACb,QAAiC,EACjC,KAA0B,EACtB,EAAE;IACN,MAAM,GAAG,GAAG,QAAQ,CAAC,CAAC,CAAC,WAAW,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;IACtE,MAAM,OAAO,GAAG,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,OAAO,GAAG,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC;IAC7F,MAAM,UAAU,GAAG,QAAQ,CAAC,CAAC,CAAC,WAAW,CAAC,QAAQ,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;IAC9E,MAAM,KAAK,GAAG,QAAQ,CAAC,CAAC,CAAC,WAAW,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;IAChE,MAAM,KAAK,GAAG,QAAQ,EAAE,KAAK,IAAI,SAAS,CAAC;IAC3C,MAAM,MAAM,GAAG,QAAQ;QACnB,CAAC,CAAC,UAAU,QAAQ,CAAC,eAAe,IAAI,QAAQ,CAAC,WAAW,EAAE;QAC9D,CAAC,CAAC,YAAY,CAAC;IACnB,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,SAAS,KAAK,CAAC,WAAW,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,WAAW,CAAC;IAChF,MAAM,IAAI,GAAG,GAAG,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,GAAG,IAAI,OAAO,IAAI,UAAU,IAAI,KAAK,IAAI,KAAK,IAAI,MAAM,IAAI,KAAK,EAAE,CAAC;IAExG,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,IAAI,QAAQ,CAAC,CAAC;AAC5C,CAAC,CAAC;AAEF,MAAM,WAAW,GAAG,CAAC,OAAe,EAAU,EAAE;IAC5C,MAAM,KAAK,GAAG,EAAE,CAAC;IACjB,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC;IACrD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,GAAG,KAAK,CAAC,CAAC;IAE9C,OAAO,IAAI,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,GAAG,CAAC,MAAM,CAAC,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC;AAClE,CAAC,CAAC;AAEF,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;IACnB,MAAM,OAAO,GAAG,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAC5B,MAAM,KAAK,GAAG,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAC1B,MAAM,eAAe,GAAG,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAEpC,IAAI,CAAC;QACD,QAAQ,OAAO,EAAE,CAAC;YACd,KAAK,SAAS;gBACV,MAAM,OAAO,CAAC,KAAK,CAAC,CAAC;gBACrB,MAAM;YACV,KAAK,UAAU;gBACX,MAAM,QAAQ,CAAC,KAAK,EAAE,eAAe,CAAC,CAAC;gBACvC,MAAM;YACV;gBACI,KAAK,EAAE,CAAC;gBACR,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;QAC7B,CAAC;IACL,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACb,IAAI,OAAO,KAAK,UAAU;YAAE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACvD,OAAO,CAAC,KAAK,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;QACtE,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;IACzB,CAAC;AACL,CAAC"}
package/dist/client.d.ts CHANGED
@@ -2,13 +2,19 @@ import { type DownloadProgressEventMode } from './torrent/download';
2
2
  import { Torrent } from './torrent/session/index';
3
3
  import type { TorrentMetadata } from './torrent/types';
4
4
  import type { TorrentFileSelection } from './torrent/file-selection';
5
+ import type { PeerInfo } from './tracker/types';
5
6
  export declare enum DownloadState {
6
7
  PARSING = "parsing",
7
8
  TRACKING = "tracking",
8
9
  CONNECTING = "connecting",
9
10
  DOWNLOADING = "downloading"
10
11
  }
12
+ export type ClientDht = {
13
+ lookupPeers(infoHash: Uint8Array): Promise<PeerInfo[]>;
14
+ close?(): void;
15
+ };
11
16
  export type ClientConfig = {
17
+ dht?: ClientDht | false;
12
18
  files?: TorrentFileSelection;
13
19
  maxInFlightRequestsPerPeer?: number;
14
20
  maxConnecting?: number;
@@ -37,12 +43,20 @@ type DownloadInput = {
37
43
  export declare class Client {
38
44
  private readonly config;
39
45
  private readonly peerId;
46
+ private readonly dhtNodeId;
47
+ private readonly dht?;
48
+ private readonly torrents;
49
+ private closed;
40
50
  constructor(config?: ClientConfig);
41
51
  download(input: DownloadInput, options?: DownloadOptions): Promise<Torrent>;
42
52
  inspect(input: InspectInput, options?: {
43
53
  timeout?: number;
44
54
  }): Promise<TorrentMetadata>;
55
+ close(): void;
56
+ private discoverPeers;
45
57
  private trackPeers;
58
+ private trackTorrent;
59
+ private assertOpen;
46
60
  }
47
61
  export type DownloadOptions = {
48
62
  announcePort?: number;
@@ -1,5 +1,6 @@
1
1
  import { BunTorrentError } from './utils/errors';
2
2
  export declare enum ClientErrorCode {
3
+ CLOSED = "CLIENT_CLOSED",
3
4
  INVALID_FILE_SELECTION = "CLIENT_INVALID_FILE_SELECTION",
4
5
  UNSUPPORTED_TORRENT_FILE_INPUT = "CLIENT_UNSUPPORTED_TORRENT_FILE_INPUT"
5
6
  }
@@ -1,6 +1,7 @@
1
1
  import { BunTorrentError } from './utils/errors';
2
2
  export var ClientErrorCode;
3
3
  (function (ClientErrorCode) {
4
+ ClientErrorCode["CLOSED"] = "CLIENT_CLOSED";
4
5
  ClientErrorCode["INVALID_FILE_SELECTION"] = "CLIENT_INVALID_FILE_SELECTION";
5
6
  ClientErrorCode["UNSUPPORTED_TORRENT_FILE_INPUT"] = "CLIENT_UNSUPPORTED_TORRENT_FILE_INPUT";
6
7
  })(ClientErrorCode || (ClientErrorCode = {}));
@@ -1 +1 @@
1
- {"version":3,"file":"client.error.js","sourceRoot":"","sources":["../src/client.error.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAEjD,MAAM,CAAN,IAAY,eAGX;AAHD,WAAY,eAAe;IACvB,2EAAwD,CAAA;IACxD,2FAAwE,CAAA;AAC5E,CAAC,EAHW,eAAe,KAAf,eAAe,QAG1B;AAED,MAAM,OAAO,WAAY,SAAQ,eAAe;IAC5C,YAAY,IAAqB,EAAE,OAAe;QAC9C,KAAK,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IACzB,CAAC;CACJ"}
1
+ {"version":3,"file":"client.error.js","sourceRoot":"","sources":["../src/client.error.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAEjD,MAAM,CAAN,IAAY,eAIX;AAJD,WAAY,eAAe;IACvB,2CAAwB,CAAA;IACxB,2EAAwD,CAAA;IACxD,2FAAwE,CAAA;AAC5E,CAAC,EAJW,eAAe,KAAf,eAAe,QAI1B;AAED,MAAM,OAAO,WAAY,SAAQ,eAAe;IAC5C,YAAY,IAAqB,EAAE,OAAe;QAC9C,KAAK,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IACzB,CAAC;CACJ"}
package/dist/client.js CHANGED
@@ -9,6 +9,8 @@ import { getUnknownSelectedFiles, normalizeTorrentFileSelection } from './torren
9
9
  import { defaults } from './configs/defaults';
10
10
  import { BunTorrentError } from './utils/errors';
11
11
  import { parseMagnet } from './magnet';
12
+ import { DhtClient } from './dht';
13
+ import { createDhtNodeId } from './dht/utils/distance';
12
14
  export var DownloadState;
13
15
  (function (DownloadState) {
14
16
  DownloadState["PARSING"] = "parsing";
@@ -19,17 +21,27 @@ export var DownloadState;
19
21
  export class Client {
20
22
  config;
21
23
  peerId;
24
+ dhtNodeId;
25
+ dht;
26
+ torrents = new Set();
27
+ closed = false;
22
28
  constructor(config = {}) {
23
29
  this.config = config;
24
30
  this.peerId = createPeerId();
31
+ this.dhtNodeId = createDhtNodeId();
32
+ this.dht =
33
+ config.dht === false
34
+ ? undefined
35
+ : (config.dht ?? new DhtClient({ nodeId: this.dhtNodeId }));
25
36
  }
26
37
  async download(input, options = {}) {
38
+ this.assertOpen();
27
39
  options.onChangeState?.(DownloadState.PARSING);
28
40
  const meta = input.meta ?? (await this.inspect(input, { timeout: options.trackerTimeoutMs }));
29
41
  const downloadConfig = resolveDownloadConfig(this.config, options);
30
42
  assertValidFileSelection(meta, downloadConfig.files);
31
43
  options.onChangeState?.(DownloadState.TRACKING);
32
- const peers = await this.trackPeers(meta, options, downloadConfig);
44
+ const peers = await this.discoverPeers(meta, options, downloadConfig);
33
45
  options.onChangeState?.(DownloadState.CONNECTING);
34
46
  const pool = await openPeerPool(peers, {
35
47
  infoHash: meta.infoHash,
@@ -41,7 +53,7 @@ export class Client {
41
53
  timeoutMs: downloadConfig.peerConnectTimeoutMs,
42
54
  });
43
55
  options.onChangeState?.(DownloadState.DOWNLOADING);
44
- return new Torrent(meta, pool, new DownloadManager({
56
+ const torrent = new Torrent(meta, pool, new DownloadManager({
45
57
  metadata: meta,
46
58
  files: downloadConfig.files,
47
59
  outputDirectory: downloadConfig.outputDirectory,
@@ -51,17 +63,46 @@ export class Client {
51
63
  requestTimeoutMs: downloadConfig.requestTimeoutMs,
52
64
  speedSampleIntervalMs: downloadConfig.speedSampleIntervalMs,
53
65
  }), normalizeTorrentFileSelection(downloadConfig.files), downloadConfig.seed);
66
+ this.trackTorrent(torrent);
67
+ return torrent;
54
68
  }
55
69
  async inspect(input, options) {
70
+ this.assertOpen();
56
71
  if ('torrentFile' in input && input.torrentFile !== undefined) {
57
72
  const bytes = await readTorrentFile(input.torrentFile);
58
73
  return parseTorrent(bytes);
59
74
  }
60
75
  if ('magnet' in input && input.magnet !== undefined && input.magnet !== null) {
61
- return parseMagnet(input.magnet, this.peerId, options);
76
+ return parseMagnet(input.magnet, this.peerId, { ...options, dht: this.dht });
62
77
  }
63
78
  throw new BunTorrentError('No input provided', 'NO_INPUT');
64
79
  }
80
+ close() {
81
+ if (this.closed)
82
+ return;
83
+ this.closed = true;
84
+ for (const torrent of this.torrents)
85
+ torrent.close();
86
+ this.torrents.clear();
87
+ this.dht?.close?.();
88
+ }
89
+ async discoverPeers(meta, options, config) {
90
+ const peers = new Map();
91
+ for (const peer of await this.trackPeers(meta, options, config)) {
92
+ peers.set(peerKey(peer), peer);
93
+ }
94
+ if (peers.size > 0 || !this.dht)
95
+ return [...peers.values()];
96
+ try {
97
+ for (const peer of await this.dht.lookupPeers(meta.infoHash)) {
98
+ peers.set(peerKey(peer), peer);
99
+ }
100
+ }
101
+ catch {
102
+ return [...peers.values()];
103
+ }
104
+ return [...peers.values()];
105
+ }
65
106
  async trackPeers(meta, options, config) {
66
107
  try {
67
108
  return await trackPeers({
@@ -77,11 +118,22 @@ export class Client {
77
118
  throw error;
78
119
  }
79
120
  }
121
+ trackTorrent(torrent) {
122
+ this.torrents.add(torrent);
123
+ torrent.on('close', () => this.torrents.delete(torrent));
124
+ void torrent.done.then(() => this.torrents.delete(torrent), () => this.torrents.delete(torrent));
125
+ }
126
+ assertOpen() {
127
+ if (!this.closed)
128
+ return;
129
+ throw new ClientError(ClientErrorCode.CLOSED, 'Torrent client is closed');
130
+ }
80
131
  }
81
132
  const isNonFatalTrackerError = (error) => error instanceof TrackerError &&
82
133
  (error.code === TrackerErrorCode.ANNOUNCE_FAILED ||
83
134
  error.code === TrackerErrorCode.NO_PEERS ||
84
135
  error.code === TrackerErrorCode.NO_SUPPORTED_TRACKERS);
136
+ const peerKey = (peer) => `${peer.ip}:${peer.port}`;
85
137
  const resolveDownloadConfig = (config, options) => ({
86
138
  files: options.files ?? config.files ?? null,
87
139
  maxInFlightRequestsPerPeer: options.maxInFlightRequestsPerPeer ??
@@ -1 +1 @@
1
- {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
@@ -22,6 +22,22 @@ export declare const defaults: {
22
22
  readonly announcePort: 6881;
23
23
  readonly timeoutMs: 5000;
24
24
  };
25
+ readonly dht: {
26
+ readonly bootstrapNodes: readonly [{
27
+ readonly host: "router.bittorrent.com";
28
+ readonly port: 6881;
29
+ }, {
30
+ readonly host: "router.utorrent.com";
31
+ readonly port: 6881;
32
+ }, {
33
+ readonly host: "dht.transmissionbt.com";
34
+ readonly port: 6881;
35
+ }];
36
+ readonly lookupConcurrency: 8;
37
+ readonly maxLookupRounds: 8;
38
+ readonly peerCacheTtlMs: number;
39
+ readonly queryTimeoutMs: 5000;
40
+ };
25
41
  readonly magnet: {
26
42
  readonly trackerTimeoutMs: 3000;
27
43
  readonly peerTimeoutMs: 5000;
@@ -22,6 +22,17 @@ export const defaults = {
22
22
  announcePort: 6881,
23
23
  timeoutMs: 5_000,
24
24
  },
25
+ dht: {
26
+ bootstrapNodes: [
27
+ { host: 'router.bittorrent.com', port: 6881 },
28
+ { host: 'router.utorrent.com', port: 6881 },
29
+ { host: 'dht.transmissionbt.com', port: 6881 },
30
+ ],
31
+ lookupConcurrency: 8,
32
+ maxLookupRounds: 8,
33
+ peerCacheTtlMs: 5 * 60_000,
34
+ queryTimeoutMs: 5_000,
35
+ },
25
36
  magnet: {
26
37
  trackerTimeoutMs: 3_000,
27
38
  peerTimeoutMs: 5_000,
@@ -1 +1 @@
1
- {"version":3,"file":"defaults.js","sourceRoot":"","sources":["../../src/configs/defaults.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,QAAQ,GAAG;IACpB,MAAM,EAAE;QACJ,SAAS,EAAE,EAAE,GAAG,IAAI;KACvB;IACD,KAAK,EAAE;QACH,iBAAiB,EAAE,EAAE;QACrB,cAAc,EAAE,CAAC;QACjB,aAAa,EAAE,EAAE;QACjB,gBAAgB,EAAE,KAAK;KAC1B;IACD,QAAQ,EAAE;QACN,0BAA0B,EAAE,GAAG;QAC/B,2BAA2B,EAAE,CAAC;QAC9B,gBAAgB,EAAE,MAAM;QACxB,IAAI,EAAE,KAAK;KACd;IACD,QAAQ,EAAE;QACN,MAAM,EAAE,OAAO;QACf,qBAAqB,EAAE,GAAG;KAC7B;IACD,QAAQ,EAAE;QACN,YAAY,EAAE,IAAI;QAClB,SAAS,EAAE,KAAK;KACnB;IACD,MAAM,EAAE;QACJ,gBAAgB,EAAE,KAAK;QACvB,aAAa,EAAE,KAAK;KACvB;CACK,CAAC"}
1
+ {"version":3,"file":"defaults.js","sourceRoot":"","sources":["../../src/configs/defaults.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,QAAQ,GAAG;IACpB,MAAM,EAAE;QACJ,SAAS,EAAE,EAAE,GAAG,IAAI;KACvB;IACD,KAAK,EAAE;QACH,iBAAiB,EAAE,EAAE;QACrB,cAAc,EAAE,CAAC;QACjB,aAAa,EAAE,EAAE;QACjB,gBAAgB,EAAE,KAAK;KAC1B;IACD,QAAQ,EAAE;QACN,0BAA0B,EAAE,GAAG;QAC/B,2BAA2B,EAAE,CAAC;QAC9B,gBAAgB,EAAE,MAAM;QACxB,IAAI,EAAE,KAAK;KACd;IACD,QAAQ,EAAE;QACN,MAAM,EAAE,OAAO;QACf,qBAAqB,EAAE,GAAG;KAC7B;IACD,QAAQ,EAAE;QACN,YAAY,EAAE,IAAI;QAClB,SAAS,EAAE,KAAK;KACnB;IACD,GAAG,EAAE;QACD,cAAc,EAAE;YACZ,EAAE,IAAI,EAAE,uBAAuB,EAAE,IAAI,EAAE,IAAI,EAAE;YAC7C,EAAE,IAAI,EAAE,qBAAqB,EAAE,IAAI,EAAE,IAAI,EAAE;YAC3C,EAAE,IAAI,EAAE,wBAAwB,EAAE,IAAI,EAAE,IAAI,EAAE;SACjD;QACD,iBAAiB,EAAE,CAAC;QACpB,eAAe,EAAE,CAAC;QAClB,cAAc,EAAE,CAAC,GAAG,MAAM;QAC1B,cAAc,EAAE,KAAK;KACxB;IACD,MAAM,EAAE;QACJ,gBAAgB,EAAE,KAAK;QACvB,aAAa,EAAE,KAAK;KACvB;CACK,CAAC"}
@@ -0,0 +1,52 @@
1
+ import { KrpcTransactionIdGenerator, type KrpcResponse } from './krpc';
2
+ import { DhtRoutingTable } from './RoutingTable';
3
+ import { type CreateUdpSocket } from '../utils/UdpSocket';
4
+ import type { PeerInfo } from '../tracker/types';
5
+ export type DhtEndpoint = {
6
+ host: string;
7
+ port: number;
8
+ };
9
+ export type DhtClientOptions = {
10
+ nodeId: Uint8Array;
11
+ bootstrapNodes?: DhtEndpoint[];
12
+ lookupConcurrency?: number;
13
+ maxLookupRounds?: number;
14
+ peerCacheTtlMs?: number;
15
+ timeoutMs?: number;
16
+ routingTable?: DhtRoutingTable;
17
+ transactionIds?: KrpcTransactionIdGenerator;
18
+ createSocket?: CreateUdpSocket;
19
+ };
20
+ export declare class DhtClient {
21
+ readonly routingTable: DhtRoutingTable;
22
+ private readonly nodeId;
23
+ private readonly bootstrapNodes;
24
+ private readonly lookupConcurrency;
25
+ private readonly maxLookupRounds;
26
+ private readonly peerCacheTtlMs;
27
+ private readonly timeoutMs;
28
+ private readonly transactionIds;
29
+ private readonly createSocket;
30
+ private readonly pending;
31
+ private readonly peerCache;
32
+ private socket;
33
+ private starting;
34
+ private closed;
35
+ constructor(options: DhtClientOptions);
36
+ start(): Promise<void>;
37
+ close(): void;
38
+ ping(endpoint: DhtEndpoint): Promise<KrpcResponse>;
39
+ findNode(endpoint: DhtEndpoint, target: Uint8Array): Promise<KrpcResponse>;
40
+ getPeers(endpoint: DhtEndpoint, infoHash: Uint8Array): Promise<KrpcResponse>;
41
+ rememberPeers(infoHash: Uint8Array, peers: PeerInfo[]): void;
42
+ bootstrap(nodes?: DhtEndpoint[], target?: Uint8Array): Promise<void>;
43
+ lookupPeers(infoHash: Uint8Array): Promise<PeerInfo[]>;
44
+ private sendQuery;
45
+ private openSocket;
46
+ private createQueryMessage;
47
+ private handleData;
48
+ private addCompactNodes;
49
+ private getCachedPeers;
50
+ private resolveEndpoint;
51
+ private rejectAll;
52
+ }