[FEATURE] - Improve UDP response error handling;
#16 opened on Nov 3, 2025
Repository metrics
- Stars
- (0 stars)
- PR merge metrics
- (No merged PRs in 30d)
Description
Description
The UDP tracker only checks for a minimum data length of 8 bytes, but different UDP tracker actions require different minimum response lengths. This can lead to incomplete parsing or incorrect error handling.
Location
File: lib/src/tracker/udp_tracker_base.dart
Line: 116
Current Code
var datagram = _socket?.receive();
if (datagram == null || datagram.data.length < 8) { // ❌ Only checks minimum 8 bytes
close();
completer.completeError('Wrong datas');
return;
}
Expected Behavior
Different UDP tracker actions require different minimum response lengths according to BEP 0015:
-
Connect Response (Action 0): Minimum 16 bytes
- 4 bytes: action
- 4 bytes: transaction_id
- 8 bytes: connection_id
-
Announce Response (Action 1): Minimum 20 bytes
- 4 bytes: action
- 4 bytes: transaction_id
- 4 bytes: interval
- 4 bytes: leechers (incomplete)
- 4 bytes: seeders (complete)
- Variable: peers (IPv4: 6 bytes each, IPv6: 18 bytes each)
-
Scrape Response (Action 2): Minimum 8 bytes + (12 bytes × number of info_hashes)
- 4 bytes: action
- 4 bytes: transaction_id
- 12 bytes per info_hash: complete, downloaded, incomplete
-
Error Response (Action 3): Minimum 8 bytes
- 4 bytes: action
- 4 bytes: transaction_id
- Variable: error message (string)
Proposed Implementation
Add action-specific validation in _processAnnounceResponseData:
void _processAnnounceResponseData(Uint8List data, Map options,
List<CompactAddress> address, Completer completer) async {
if (isClosed) {
if (!completer.isCompleted) completer.completeError('Tracker Closed');
return;
}
var view = ByteData.view(data.buffer);
var tid = view.getUint32(4);
if (tid == transcationIdNum) {
var action = view.getUint32(0);
// Validate minimum length based on action
if (!_validateResponseLength(data, action)) {
if (!completer.isCompleted) {
completer.completeError('Invalid response length for action $action');
}
close();
return;
}
// ... rest of processing ...
}
}
bool _validateResponseLength(Uint8List data, int action) {
switch (action) {
case 0: // Connect
return data.length >= 16;
case 1: // Announce
return data.length >= 20; // Minimum without peers
case 2: // Scrape
// For scrape, need to know number of info_hashes
// This should be checked in UDPScrape class
return data.length >= 8;
case 3: // Error
return data.length >= 8;
default:
return false;
}
}
For Scrape, validate in udp_scrape.dart:
@override
dynamic processResponseData(
Uint8List data, int action, Iterable<CompactAddress> addresses) {
if (action != 2) {
throw Exception('The Action in the returned data does not match.');
}
// Validate minimum length
var minLength = 8 + (infoHashSet.length * 12);
if (data.length < minLength) {
throw Exception(
'Invalid scrape response length: expected at least $minLength bytes, '
'got ${data.length} bytes',
);
}
// ... rest of processing ...
}
Improve error messages with expected vs actual length:
if (datagram == null || datagram.data.length < 8) {
close();
var errorMsg = datagram == null
? 'No data received'
: 'Invalid response length: expected at least 8 bytes, got ${datagram.data.length}';
completer.completeError(errorMsg);
return;
}
Impact
- Severity: Medium (Quality Improvement)
- Affected: All UDP tracker operations
- Benefits:
- Better error detection for malformed responses
- Clearer error messages with expected vs actual lengths
- Prevention of incomplete parsing
- Better debugging information
Additional Context
Proper length validation helps:
- Detect malformed or truncated responses
- Prevent
IndexOutOfBoundsexceptions - Identify network issues
- Debug tracker communication problems