fix: use transport peer ID as P2PEvent source for correct message routing#9
fix: use transport peer ID as P2PEvent source for correct message routing#9
Conversation
Code reviewNo issues found. Checked for bugs and CLAUDE.md compliance. |
e328261 to
5fd659e
Compare
…ting Use the transport-level peer ID (hex-encoded ant-quic PeerId) as P2PEvent::Message.source instead of the "from" field from the JSON protocol message. This fixes a routing bug where consumers couldn't pass the event source back to send_message() because the ID namespace didn't match the peers map / active_connections keys. Refactors: - Hoist ant_peer_id_to_string import to module level - Promote KEEPALIVE_PAYLOAD to module-level constant - Extract parse_protocol_message() helper (DRY) - Remove dead handle_received_message method - Move inline tokio::time imports to module level Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
5fd659e to
49421d8
Compare
|
@claude please review this PR |
|
Claude finished @mickvandijke's task in 1m 36s —— View job Code Review ✅SummaryThis PR correctly fixes a critical message routing bug. The change ensures that What Changed
CLAUDE.md Compliance ✅
Code Quality ✅
Issues FoundNone. This is a well-implemented fix with proper testing and documentation. RecommendationsThis PR is ready to merge. The fix correctly addresses the routing mismatch while improving code quality and security. --- | |
…ew() to start() P2PNode::new() and start() both called start_network_listeners() and start_message_receiving_system(), spawning duplicate accept and receive loops competing on the same QUIC endpoint. This caused messages to be randomly split between loops, leading to flaky delivery. Now new() only constructs the struct; start() is the single place where background loops are spawned. All callers updated to call start() after new(). Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…loops fix: remove duplicate receive loops in P2PNode Nice one Mick,
Code Review: PR #9 - fix: use transport peer ID as P2PEvent sourceHey @mickvandijke, excellent security fix! Here's my comprehensive review including ADR compliance check. 📝 SummaryThis PR fixes a security issue where ✅ ADR Compliance CheckADR-001: Multi-Layer Architecture ✅ COMPLIANTThe fix aligns perfectly with the layer separation principle:
Before: P2PEvent source used application-layer This correctly respects the boundary between layers - the transport layer's authenticated peer ID is the source of truth, not application-layer claims. ADR-002: Delegated Transport via ant-quic ✅ COMPLIANTThe fix properly uses the adapter layer: use crate::transport::ant_quic_adapter::{DualStackNetworkNode, ant_peer_id_to_string};
// ...
let transport_peer_id = ant_peer_id_to_string(&peer_id);This follows the ADR-002 pattern: "The adapter layer translates between saorsa-core abstractions and ant-quic primitives." 🔒 Security ImprovementsThis is a significant security fix. The old code trusted the // OLD (vulnerable)
source: from.to_string(), // Attacker could spoof any peer IDThe new code uses the authenticated transport peer ID: // NEW (secure)
source: source.to_string(), // From QUIC connection, can't be spoofedThe docstring correctly documents this:
✅ What Looks Good
|
…ing) Implements 11 hardening improvements from PR #21 review comments: 1. Request Leak/Cleanup: - Added RAII RequestCleanupGuard for automatic cleanup on drop/cancel - Atomic check+insert under single write lock to prevent races 2. Input Validation: - Added TransportError::ValidationError for input validation errors - validate_protocol_name() now uses ValidationError instead of StreamError 3. Timeout Handling: - Added MIN_REQUEST_TIMEOUT (100ms) to prevent Duration::ZERO immediate timeout - send_request() clamps timeout to [100ms, 5min] range 4. Response Routing: - Improved logging for failed pending.send() to clarify timeout scenario 5. Documentation: - Added documentation to ReplicationResult clarifying remote-only counts - Fixed brittle error assertion in tests to check error variant 6. Testing: - New tests/request_response_e2e_test.rs with 7 comprehensive tests: * Successful request/response routing * Timeout cleanup behavior * Invalid protocol rejection (empty, /, \, \0) * Protocol validation in send_response() * Minimum timeout enforcement * Trust reporting on failure Items already correct (verified): - #3: Protocol validation in send_response() already present - #6: Response-origin mismatch uses get() before remove() - #7: Unmatched /rr/ responses already suppressed - #9: Trust reporting on send_message() failure already implemented - #10: PeerStoreOutcome docs correct (no latency mention) Closes #23 Co-authored-by: David Irvine <dirvine@users.noreply.github.com>
Summary
fromfield from the JSON message payload as the source, butsend_message()looks up peers by their transport-level peer IDPeerIdto the hex string used in the peers map and uses that as the event sourceTest plan
cargo testpassescargo clippy -- -D warnings -D clippy::unwrap_used -D clippy::expect_usedpasses🤖 Generated with Claude Code