Skip to content

Conversation

@josecelano
Copy link
Member

Summary

Implements socket address uniqueness validation for tracker configuration as described in issue #255. This prevents configuration errors where multiple services attempt to bind to the same socket address with the same protocol, which would result in runtime failures.

Changes

Core Implementation

  • BindingAddress value object (src/domain/tracker/binding_address.rs)

    • Combines SocketAddr with Protocol for type-safe binding representation
    • Implements Hash and Eq for HashMap-based duplicate detection
    • 7 comprehensive unit tests
  • TrackerConfig validation (src/domain/tracker/config/mod.rs)

    • validate() - Main validation orchestrator
    • collect_bindings() - Gathers all socket bindings with service names
    • check_for_conflicts() - Detects duplicate bindings
    • register_binding() / register_trackers() - DRY helper methods
    • HasBindAddress trait for generic tracker handling
    • 8 validation tests covering all scenarios
  • TrackerConfigError with tiered help system

    • Brief Display with actionable tip
    • Detailed .help() method for troubleshooting
    • Follows error handling conventions from docs/contributing/error-handling.md

Integration

  • Validation integrated at DTO boundary (TrackerSection.to_tracker_config())
  • Error propagation through CreateConfigError
  • 2 integration tests for DTO validation

Validation Rules

Rejects: Same protocol + same socket address

  • Multiple HTTP services on same TCP port
  • Multiple UDP trackers on same port
  • HTTP tracker + HTTP API conflict
  • HTTP tracker + Health Check API conflict

Allows: Different protocols sharing same port

  • UDP tracker + HTTP tracker on same port (different protocols)
  • Same port on different IP addresses

Manual E2E Testing

Tested with real environment configurations to verify production behavior:

Test Case 1: TCP Conflict ❌ (Correctly Rejected)

Configuration: HTTP Tracker and HTTP API both on 0.0.0.0:7070 (TCP)

{
  "http_trackers": [{"bind_address": "0.0.0.0:7070"}],
  "http_api": {"bind_address": "0.0.0.0:7070", "admin_token": "..."}
}

Result:

❌ Configuration validation failed: Socket address conflict: 'HTTP Tracker #1', 'HTTP API' cannot bind to 0.0.0.0:7070 (TCP)
Tip: Assign different port numbers to each service

Test Case 2: UDP Conflict ❌ (Correctly Rejected)

Configuration: Two UDP trackers on same address

{
  "udp_trackers": [
    {"bind_address": "0.0.0.0:6969"},
    {"bind_address": "0.0.0.0:6969"}
  ]
}

Result:

❌ Socket address conflict: 'UDP Tracker #1', 'UDP Tracker #2' cannot bind to 0.0.0.0:6969 (UDP)
Tip: Assign different port numbers to each service

Test Case 3: Valid Configuration ✅ (Correctly Accepted)

Configuration: All services on unique addresses

{
  "udp_trackers": [{"bind_address": "0.0.0.0:6969"}],
  "http_trackers": [{"bind_address": "0.0.0.0:7070"}],
  "http_api": {"bind_address": "0.0.0.0:1212"},
  "health_check_api": {"bind_address": "127.0.0.1:1313"}
}

Result: ✅ Environment created successfully

Test Case 4: Cross-Protocol ✅ (Correctly Accepted)

Configuration: UDP and TCP sharing same port (different protocols)

{
  "udp_trackers": [{"bind_address": "0.0.0.0:7070"}],
  "http_trackers": [{"bind_address": "0.0.0.0:7070"}]
}

Result: ✅ Environment created successfully (UDP and TCP use separate port spaces)

Automated Testing

  • ✅ 1613 unit tests passing
  • ✅ All linters passing (markdown, YAML, TOML, cspell, clippy, rustfmt, shellcheck)
  • ✅ Documentation builds successfully
  • ✅ E2E infrastructure lifecycle tests passing
  • ✅ E2E deployment workflow tests passing
  • ✅ Total pre-commit time: 4m 45s

Code Quality Improvements

This PR includes several refactoring commits that improve code quality:

  1. Extract binding collection - Separate method for gathering bindings
  2. Extract conflict checking - Focused method for duplicate detection
  3. Eliminate duplication - DRY helpers for binding registration

Benefits:

  • Single Responsibility Principle compliance
  • Better testability with focused methods
  • Reduced code duplication (~30 lines → ~15 lines)
  • Clear separation of concerns
  • Easier to maintain and extend

Documentation

  • Comprehensive rustdoc comments on all public APIs
  • Error help text with platform-specific troubleshooting
  • References to docs/external-issues/tracker/udp-tcp-port-sharing-allowed.md

Related

- Add HealthCheckApiConfig domain type with bind_address field
- Add HealthCheckApiSection DTO with validation (rejects port 0)
- Default bind address: 127.0.0.1:1313
- Update TrackerConfig and TrackerSection with health_check_api field
- Add comprehensive unit tests for validation logic
- Update all test fixtures and E2E config generators
- Regenerate environment-config.json schema
- Fix all doc test examples

The Health Check API is now fully configurable throughout the application
with proper validation and comprehensive test coverage.
- Convert config.rs into folder module (config/)
- Extract TrackerCoreConfig → config/core.rs (2 tests)
- Extract UdpTrackerConfig → config/udp.rs (3 tests)
- Extract HttpTrackerConfig → config/http.rs (3 tests)
- Extract HttpApiConfig → config/http_api.rs (3 tests)
- Extract HealthCheckApiConfig → config/health_check_api.rs (3 tests)
- Keep TrackerConfig in config/mod.rs (3 integration tests)
- Improve code organization and maintainability
- All 1582 tests passing
- Convert core.rs into folder module (config/core/)
- Move database module into config/core/database/
- Update imports to reflect new structure
- Database types now exported through config module hierarchy
- Improves logical grouping (database is part of core config)
- All 1582 tests passing
- All linters passing
…p system

- Add BindingAddress value object combining SocketAddr with Protocol
- Add TrackerConfig::validate() method to detect socket address conflicts
- Add TrackerConfigError enum with DuplicateSocketAddress variant
- Implement tiered help system (brief Display + detailed .help() method)
- Integrate validation at DTO boundary (TrackerSection.to_tracker_config)
- Add comprehensive unit tests for validation logic
- Add integration tests for DTO validation

Follows error handling conventions from docs/contributing/error-handling.md
- Extract collect_bindings() private method from validate()
- Improves Single Responsibility Principle compliance
- Makes validate() method more focused on conflict detection
- Better separation of concerns: collection vs validation
- Extract check_for_conflicts() private method from validate()
- Further improves Single Responsibility Principle
- Now validate() is a clean orchestrator of two focused methods
- Three-level separation: collect → check → report error
- Extract register_binding() helper to remove repeated HashMap operations
- Extract register_trackers() to handle multiple tracker instances generically
- Add HasBindAddress trait for uniform tracker handling
- Service names now declared once at call site (DRY principle)
- Reduces code from ~30 lines to ~15 lines in collect_bindings()
- Improves testability with focused helper methods
@josecelano josecelano self-assigned this Dec 29, 2025
@josecelano
Copy link
Member Author

ACK dc153f0

@josecelano josecelano merged commit 4a4f120 into main Dec 29, 2025
34 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add Socket Address Uniqueness Validation for Tracker Configuration

2 participants