Skip to content

Commit fe3b68f

Browse files
committed
Added custom tracker support for webtorrent
Signed-off-by: Robert Gogete <[email protected]>
1 parent 0b369ab commit fe3b68f

File tree

6 files changed

+63
-11
lines changed

6 files changed

+63
-11
lines changed

README.md

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,20 @@ A TypeScript package that provides peer-to-peer file sharing capabilities using
1515
- Robust error handling and fallback mechanisms
1616
- Real-time download progress tracking
1717
- Cascading network topology detection and error reporting
18-
- Host your own Gun.js relay for decentralized P2P
19-
- WebTorrent support for browser-based P2P file sharing
18+
- Host your own Gun.js relay for decentralized P2P
19+
- WebTorrent support for browser-based P2P file sharing
20+
- **Custom WebTorrent tracker configuration** for private or specialized networks
2021

2122
## Installation
2223

2324
```bash
2425
npm install dig-nat-tools
2526
```
2627

28+
## Quick Links
29+
30+
- [Custom WebTorrent Tracker Configuration Guide](./CUSTOM_TRACKERS.md) - Learn how to configure custom trackers for WebTorrent
31+
2732
## Running the Example
2833

2934
To test the package with the included example:

src/client.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@ export interface FileClientOptions {
2424
peers?: string[]; // Gun.js peer URLs
2525
namespace?: string; // Gun.js namespace
2626
logger?: Logger; // Optional logger for debug output
27+
webTorrent?: {
28+
trackers?: string[]; // Custom tracker URLs
29+
};
2730
}
2831

2932

@@ -258,7 +261,11 @@ export class FileClient extends EventEmitter implements IFileClient {
258261

259262
// Initialize the shared WebTorrent manager if not already done
260263
if (!webTorrentManager.isAvailable()) {
261-
await webTorrentManager.initialize(this.logger);
264+
const webTorrentOptions = this.options.webTorrent?.trackers
265+
? { trackers: this.options.webTorrent.trackers }
266+
: undefined;
267+
268+
await webTorrentManager.initialize(this.logger, webTorrentOptions);
262269
}
263270

264271
// Set up event listeners (only done once)

src/host.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@ export interface HostOptions {
3333
peers: string[]; // Gun.js peer URLs
3434
namespace?: string; // Registry namespace
3535
};
36+
webTorrent?: {
37+
trackers?: string[]; // Custom tracker URLs
38+
};
3639
}
3740

3841
export class FileHost implements IFileHost {
@@ -335,9 +338,13 @@ export class FileHost implements IFileHost {
335338
try {
336339
this.logger.debug(`🔄 Initializing shared WebTorrent manager...`);
337340

338-
// Initialize the shared WebTorrent manager
341+
// Initialize the shared WebTorrent manager with custom trackers if provided
339342
if (!webTorrentManager.isAvailable()) {
340-
await webTorrentManager.initialize(this.logger);
343+
const webTorrentOptions = this.options.webTorrent?.trackers
344+
? { trackers: this.options.webTorrent.trackers }
345+
: undefined;
346+
347+
await webTorrentManager.initialize(this.logger, webTorrentOptions);
341348
}
342349

343350
this.logger.debug(`✅ Shared WebTorrent manager initialized and ready`);

src/index.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,5 @@ export {
1717
// Export types for TypeScript users
1818
export type { HostOptions } from './host';
1919
export type { FileClientOptions, DownloadOptions } from './client';
20-
export type { IFileHost, IFileClient, HostCapabilities } from './interfaces';
20+
export type { IFileHost, IFileClient, HostCapabilities, WebTorrentConfig } from './interfaces';
21+
export type { WebTorrentOptions } from './webtorrent-manager';

src/interfaces.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
import { Readable } from 'stream';
22
import { DownloadOptions } from './client';
33

4+
export interface WebTorrentConfig {
5+
trackers?: string[]; // Custom tracker URLs
6+
}
7+
48
export interface HostCapabilities {
59
storeId: string;
610
// Connection methods (in order of preference)

src/webtorrent-manager.ts

Lines changed: 33 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@ interface Logger {
1010
error(message: string, ...args: unknown[]): void;
1111
}
1212

13+
export interface WebTorrentOptions {
14+
trackers?: string[]; // Custom tracker URLs
15+
}
16+
1317
export interface DownloadProgressEvent {
1418
downloaded: number; // Total bytes downloaded
1519
downloadSpeed: number; // Current download speed in bytes/second
@@ -37,6 +41,7 @@ class WebTorrentManager extends EventEmitter {
3741
private logger: Logger;
3842
private isInitialized: boolean = false;
3943
private initializationPromise: Promise<void> | null = null;
44+
private customTrackers: string[] = [];
4045

4146
private constructor() {
4247
super();
@@ -65,7 +70,7 @@ class WebTorrentManager extends EventEmitter {
6570
/**
6671
* Initialize the WebTorrent client (only once, atomically)
6772
*/
68-
public async initialize(logger?: Logger): Promise<void> {
73+
public async initialize(logger?: Logger, options?: WebTorrentOptions): Promise<void> {
6974
// If already initialized, return immediately
7075
if (this.isInitialized && this.webTorrentClient) {
7176
return;
@@ -78,7 +83,7 @@ class WebTorrentManager extends EventEmitter {
7883
}
7984

8085
// Start the initialization process atomically
81-
this.initializationPromise = this.performInitialization(logger);
86+
this.initializationPromise = this.performInitialization(logger, options);
8287

8388
try {
8489
await this.initializationPromise;
@@ -91,15 +96,30 @@ class WebTorrentManager extends EventEmitter {
9196
/**
9297
* Perform the actual initialization work
9398
*/
94-
private async performInitialization(logger?: Logger): Promise<void> {
99+
private async performInitialization(logger?: Logger, options?: WebTorrentOptions): Promise<void> {
95100
if (logger) {
96101
this.logger = logger;
97102
}
98103

104+
// Store custom trackers if provided
105+
if (options?.trackers) {
106+
this.customTrackers = options.trackers;
107+
this.logger.debug(`🔧 Custom trackers configured: ${this.customTrackers.join(', ')}`);
108+
}
109+
99110
this.logger.debug("🚀 Initializing shared WebTorrent client...");
100111

101112
try {
102-
this.webTorrentClient = new WebTorrent();
113+
const webTorrentOptions: WebTorrent.Options = {};
114+
115+
// Add custom trackers to WebTorrent client configuration if provided
116+
if (this.customTrackers.length > 0) {
117+
webTorrentOptions.tracker = {
118+
announce: this.customTrackers
119+
} as WebTorrent.Options['tracker'];
120+
}
121+
122+
this.webTorrentClient = new WebTorrent(webTorrentOptions);
103123

104124
// Set unlimited max listeners for the WebTorrent client (if method exists)
105125
if (typeof this.webTorrentClient.setMaxListeners === 'function') {
@@ -352,7 +372,15 @@ class WebTorrentManager extends EventEmitter {
352372

353373
return new Promise<string>((resolve, reject) => {
354374
try {
355-
this.webTorrentClient!.seed(filePath, (torrent) => {
375+
const seedOptions: WebTorrent.TorrentOptions = {};
376+
377+
// Add custom trackers to the torrent if configured
378+
if (this.customTrackers.length > 0) {
379+
seedOptions.announce = this.customTrackers;
380+
this.logger.debug(`🔧 Using custom trackers for seeding: ${this.customTrackers.join(', ')}`);
381+
}
382+
383+
this.webTorrentClient!.seed(filePath, seedOptions, (torrent) => {
356384
const magnetURI = torrent.magnetURI;
357385
this.logger.debug(`🧲 File seeded successfully: ${filePath}`);
358386
this.logger.debug(` Magnet URI: ${magnetURI}`);

0 commit comments

Comments
 (0)