atlet99/dtorrent_tracker_v2

[FEATURE] - Support binary tracker ID format;

Open

#15 opened on Nov 3, 2025

 (0 comments) (0 reactions) (0 assignees)Dart (0 forks)auto 404
enhancementhelp wanted

Repository metrics

Stars
 (0 stars)
PR merge metrics
 (No merged PRs in 30d)

Description

Description

The HTTP tracker stores tracker id as a string, but according to BEP 0003, it can also be binary data. The current implementation may not handle binary tracker IDs correctly.

Location

File: lib/src/tracker/http_tracker.dart
Lines: 114-115, 89

Current Code

String? _trackerId;  // ❌ Only stores as string

// In processResponseData:
if (result['tracker id'] != null) {
  _trackerId = result['tracker id'];  // Assumes string
}

// In generateQueryParameters:
if (currentTrackerId != null) params['trackerid'] = currentTrackerId!;  // String

Problem:

  • tracker id in BEP 0003 can be either a string or binary data
  • Current code assumes it's always a string
  • Binary tracker IDs may not be handled correctly

Expected Behavior

According to BEP 0003, tracker id can be:

  • A string (UTF-8 encoded)
  • Binary data (byte array)

The library should:

  1. Store tracker ID in a format that supports both (e.g., Uint8List?)
  2. Convert to string only when needed for query parameters
  3. Handle both string and binary formats from responses

Proposed Implementation

class HttpTracker extends Tracker with HttpTrackerBase {
  Uint8List? _trackerId;  // ✅ Store as binary, convert when needed
  
  // Getter that converts to string for query parameters
  String? get currentTrackerId {
    if (_trackerId == null) return null;
    
    // Try to decode as UTF-8 string
    try {
      return utf8.decode(_trackerId!);
    } catch (e) {
      // If not valid UTF-8, encode as URL-safe base64 or hex
      return base64.encode(_trackerId!);
    }
  }
  
  // Store raw tracker ID (supports both string and binary)
  Uint8List? get rawTrackerId => _trackerId;
  
  @override
  PeerEvent processResponseData(Uint8List data) {
    var result = decode(data) as Map;
    
    // Handle tracker ID (can be string or binary)
    if (result['tracker id'] != null) {
      var trackerIdValue = result['tracker id'];
      if (trackerIdValue is Uint8List) {
        // Binary format - store as-is
        _trackerId = trackerIdValue;
      } else if (trackerIdValue is String) {
        // String format - encode to bytes
        _trackerId = utf8.encode(trackerIdValue);
      } else {
        // Try to convert other types
        _log.warning('Unexpected tracker id type: ${trackerIdValue.runtimeType}');
      }
    }
    
    // ... rest of processing ...
  }
  
  @override
  Map<String, String> generateQueryParameters(Map<String, dynamic> options) {
    // ... existing code ...
    
    if (_trackerId != null) {
      var trackerIdStr = currentTrackerId;
      if (trackerIdStr != null) {
        // URL encode the tracker ID string
        params['trackerid'] = Uri.encodeQueryComponent(trackerIdStr);
      }
    }
    
    return params;
  }
}

Alternative: Support Both Formats Explicitly

class HttpTracker extends Tracker with HttpTrackerBase {
  Uint8List? _trackerIdBinary;
  String? _trackerIdString;
  
  String? get currentTrackerId {
    return _trackerIdString ?? 
           (_trackerIdBinary != null ? utf8.decode(_trackerIdBinary!) : null);
  }
  
  @override
  PeerEvent processResponseData(Uint8List data) {
    var result = decode(data) as Map;
    
    if (result['tracker id'] != null) {
      var trackerIdValue = result['tracker id'];
      if (trackerIdValue is Uint8List) {
        _trackerIdBinary = trackerIdValue;
        try {
          _trackerIdString = utf8.decode(trackerIdValue);
        } catch (e) {
          _trackerIdString = null; // Binary data, not UTF-8
        }
      } else if (trackerIdValue is String) {
        _trackerIdString = trackerIdValue;
        _trackerIdBinary = utf8.encode(trackerIdValue);
      }
    }
    
    // ... rest of processing ...
  }
}

Impact

  • Severity: Low (Compatibility Improvement)
  • Affected: HTTP tracker responses with binary tracker IDs
  • Benefits:
    • Full BEP 0003 compliance
    • Support for trackers that send binary tracker IDs
    • Better compatibility with various tracker implementations

Additional Context

Binary tracker IDs are:

  • Allowed by BEP 0003 specification
  • Used by some tracker implementations
  • Should be handled gracefully
  • Rare but important for full compliance

Related Standards

Contributor guide