-
-
Notifications
You must be signed in to change notification settings - Fork 107
refactor(routing): add upstream_addr for connection-based routing #2167
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
|
Dont use SocketAddr directly anywhere in the codebase directly for other thing than connecting to the actual socket. If you make invalid states (eg using private ips for external connections) unrepresentable at compile time it will prevent a lot of this potential errors we are fixing with endless chains of refactors. Encode the usage of addresses in the type system via newtypes (eg AdvertisedAddr instead of SocketAddr) |
I can use an ObservedAddr wrapper for SocketAddr - I'm trying to avoid relying on what a peer advertises as its own addr in messages since the message recipient has a more reliable way to determine the peer's external address from the socket info. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR implements connection-based routing for NAT traversal by separating peer identity from network addresses. The changes restructure PeerKeyLocation to use an explicit PeerAddr enum and modify connection tracking to key by SocketAddr instead of PeerId.
Key Changes:
- Introduced
PeerAddrenum (Unknown/Known) for explicit address state management - Changed
LiveTransactionTrackerand connection maps to useSocketAddrkeys - Updated
NetworkBridgetrait to route bySocketAddrinstead ofPeerId - Added
upstream_addrfield to operations for connection-based routing - Threaded
source_addrthrough operation handlers for NAT-aware routing
Reviewed changes
Copilot reviewed 26 out of 26 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| crates/core/src/transport/mod.rs | Added ObservedAddr newtype for transport-layer addresses |
| crates/core/src/ring/peer_key_location.rs | Major restructuring with PeerAddr enum and new accessor methods |
| crates/core/src/ring/live_tx.rs | Changed to track transactions by SocketAddr |
| crates/core/src/ring/connection_manager.rs | Updated connection management to use SocketAddr keys |
| crates/core/src/operations/*.rs | Added upstream_addr field and source_addr parameter to operations |
| crates/core/src/node/network_bridge/*.rs | Updated NetworkBridge trait and implementations for SocketAddr routing |
| crates/core/src/tracing/mod.rs | Updated to use new peer() accessor method |
| crates/core/src/operations/subscribe/tests.rs | Updated test code to use new PeerKeyLocation constructors |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| if sender_mut.peer().addr.ip().is_unspecified() { | ||
| sender_mut.peer().addr = remote_addr; |
Copilot
AI
Nov 29, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Attempting to mutate an immutable value. sender_mut.peer() returns a PeerId by value (not a mutable reference), so trying to assign to sender_mut.peer().addr will fail to compile. This should likely be updating the sender_mut's peer_addr field directly instead of trying to mutate through the peer() method.
| if sender_mut.peer().addr.ip().is_unspecified() { | |
| sender_mut.peer().addr = remote_addr; | |
| if sender_mut.peer.addr.ip().is_unspecified() { | |
| sender_mut.peer.addr = remote_addr; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch! Fixed in 09ed113 - now using socket_addr().is_some_and(|a| a.ip().is_unspecified()) for the check and set_addr(remote_addr) for the mutation.
[AI-assisted - Claude]
345e3e7 to
2e39f69
Compare
This commit applies all wire protocol cleanup changes from PR #2169 on top of the rebased PR #2167 base: - Remove sender field from GetMsg, PutMsg, SubscribeMsg, UpdateMsg, ConnectMsg - Use upstream_addr for routing responses instead of embedded sender fields - Delete transient_manager.rs (no longer needed) - Update freenet-macros code generation for new message structure The routing logic now derives the response target from the connection's observed address (upstream_addr) rather than trusting sender fields in messages. This is more reliable for NAT traversal scenarios. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
This commit applies all wire protocol cleanup changes from PR #2169 on top of the rebased PR #2167 base: - Remove sender field from GetMsg, PutMsg, SubscribeMsg, UpdateMsg, ConnectMsg - Use upstream_addr for routing responses instead of embedded sender fields - Delete transient_manager.rs (no longer needed) - Update freenet-macros code generation for new message structure The routing logic now derives the response target from the connection's observed address (upstream_addr) rather than trusting sender fields in messages. This is more reliable for NAT traversal scenarios. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
This commit applies all wire protocol cleanup changes from PR #2169 on top of the rebased PR #2167 base: - Remove sender field from GetMsg, PutMsg, SubscribeMsg, UpdateMsg, ConnectMsg - Use upstream_addr for routing responses instead of embedded sender fields - Delete transient_manager.rs (no longer needed) - Update freenet-macros code generation for new message structure The routing logic now derives the response target from the connection's observed address (upstream_addr) rather than trusting sender fields in messages. This is more reliable for NAT traversal scenarios. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
This commit applies all wire protocol cleanup changes from PR #2169 on top of the rebased PR #2167 base: - Remove sender field from GetMsg, PutMsg, SubscribeMsg, UpdateMsg, ConnectMsg - Use upstream_addr for routing responses instead of embedded sender fields - Delete transient_manager.rs (no longer needed) - Update freenet-macros code generation for new message structure The routing logic now derives the response target from the connection's observed address (upstream_addr) rather than trusting sender fields in messages. This is more reliable for NAT traversal scenarios. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
This commit applies all wire protocol cleanup changes from PR #2169 on top of the rebased PR #2167 base: - Remove sender field from GetMsg, PutMsg, SubscribeMsg, UpdateMsg, ConnectMsg - Use upstream_addr for routing responses instead of embedded sender fields - Delete transient_manager.rs (no longer needed) - Update freenet-macros code generation for new message structure The routing logic now derives the response target from the connection's observed address (upstream_addr) rather than trusting sender fields in messages. This is more reliable for NAT traversal scenarios. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
This commit applies all wire protocol cleanup changes from PR #2169 on top of the rebased PR #2167 base: - Remove sender field from GetMsg, PutMsg, SubscribeMsg, UpdateMsg, ConnectMsg - Use upstream_addr for routing responses instead of embedded sender fields - Delete transient_manager.rs (no longer needed) - Update freenet-macros code generation for new message structure The routing logic now derives the response target from the connection's observed address (upstream_addr) rather than trusting sender fields in messages. This is more reliable for NAT traversal scenarios. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
This commit applies all wire protocol cleanup changes from PR #2169 on top of the rebased PR #2167 base: - Remove sender field from GetMsg, PutMsg, SubscribeMsg, UpdateMsg, ConnectMsg - Use upstream_addr for routing responses instead of embedded sender fields - Delete transient_manager.rs (no longer needed) - Update freenet-macros code generation for new message structure The routing logic now derives the response target from the connection's observed address (upstream_addr) rather than trusting sender fields in messages. This is more reliable for NAT traversal scenarios. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
This commit applies all wire protocol cleanup changes from PR #2169 on top of the rebased PR #2167 base: - Remove sender field from GetMsg, PutMsg, SubscribeMsg, UpdateMsg, ConnectMsg - Use upstream_addr for routing responses instead of embedded sender fields - Delete transient_manager.rs (no longer needed) - Update freenet-macros code generation for new message structure The routing logic now derives the response target from the connection's observed address (upstream_addr) rather than trusting sender fields in messages. This is more reliable for NAT traversal scenarios. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
Should be fixed now. |
|
Claude finished @sanity's task —— View job Code Review - Connection-Based Routing (PR #2167)Reviewing part 1 of the 4-PR stack for connection-based routing (issue #2164). This PR establishes the foundation for connection-based routing by restructuring the type system and threading source address information through the codebase. Overall Assessment✅ Architecture: The refactoring successfully separates peer identity from network addresses, which is essential for NAT traversal. The design principles are sound. Critical Issues1. Newtype Usage is Inconsistent
|
58459ac to
51c0ddb
Compare
This commit applies all wire protocol cleanup changes from PR #2169 on top of the rebased PR #2167 base: - Remove sender field from GetMsg, PutMsg, SubscribeMsg, UpdateMsg, ConnectMsg - Use upstream_addr for routing responses instead of embedded sender fields - Delete transient_manager.rs (no longer needed) - Update freenet-macros code generation for new message structure The routing logic now derives the response target from the connection's observed address (upstream_addr) rather than trusting sender fields in messages. This is more reliable for NAT traversal scenarios. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
This commit applies all wire protocol cleanup changes from PR #2169 on top of the rebased PR #2167 base: - Remove sender field from GetMsg, PutMsg, SubscribeMsg, UpdateMsg, ConnectMsg - Use upstream_addr for routing responses instead of embedded sender fields - Delete transient_manager.rs (no longer needed) - Update freenet-macros code generation for new message structure The routing logic now derives the response target from the connection's observed address (upstream_addr) rather than trusting sender fields in messages. This is more reliable for NAT traversal scenarios. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
This commit applies all wire protocol cleanup changes from PR #2169 on top of the rebased PR #2167 base: - Remove sender field from GetMsg, PutMsg, SubscribeMsg, UpdateMsg, ConnectMsg - Use upstream_addr for routing responses instead of embedded sender fields - Delete transient_manager.rs (no longer needed) - Update freenet-macros code generation for new message structure The routing logic now derives the response target from the connection's observed address (upstream_addr) rather than trusting sender fields in messages. This is more reliable for NAT traversal scenarios. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
## Problem Tests were intermittently failing with "Address already in use (os error 98)" because the port reservation mechanism had a race condition: 1. reserve_local_port() bound a TCP listener, got a port, then immediately dropped it 2. The port was released back to the OS 3. Between release and when the test node actually bound to the port, another process could claim it Additionally, the reservation used TCP but nodes bind UDP, so a port could be free for TCP but already in use for UDP. ## Solution - Reserve both UDP (primary for Freenet nodes) and TCP (for WebSocket API) ports - Keep the sockets alive in a global RESERVED_SOCKETS map until explicitly released - Release ports just before node startup in the test macro to minimize the race window - Store port variables at outer scope so they're available for both config creation and later release The key insight is that we need to hold the port reservation until the moment before the node binds, then release it to allow the node to bind to that exact port. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
This commit applies all wire protocol cleanup changes from PR #2169 on top of the rebased PR #2167 base: - Remove sender field from GetMsg, PutMsg, SubscribeMsg, UpdateMsg, ConnectMsg - Use upstream_addr for routing responses instead of embedded sender fields - Delete transient_manager.rs (no longer needed) - Update freenet-macros code generation for new message structure The routing logic now derives the response target from the connection's observed address (upstream_addr) rather than trusting sender fields in messages. This is more reliable for NAT traversal scenarios. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
This commit applies all wire protocol cleanup changes from PR #2169 on top of the rebased PR #2167 base: - Remove sender field from GetMsg, PutMsg, SubscribeMsg, UpdateMsg, ConnectMsg - Use upstream_addr for routing responses instead of embedded sender fields - Delete transient_manager.rs (no longer needed) - Update freenet-macros code generation for new message structure The routing logic now derives the response target from the connection's observed address (upstream_addr) rather than trusting sender fields in messages. This is more reliable for NAT traversal scenarios. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
This commit applies all wire protocol cleanup changes from PR #2169 on top of the rebased PR #2167 base: - Remove sender field from GetMsg, PutMsg, SubscribeMsg, UpdateMsg, ConnectMsg - Use upstream_addr for routing responses instead of embedded sender fields - Delete transient_manager.rs (no longer needed) - Update freenet-macros code generation for new message structure The routing logic now derives the response target from the connection's observed address (upstream_addr) rather than trusting sender fields in messages. This is more reliable for NAT traversal scenarios. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
This commit applies all wire protocol cleanup changes from PR #2169 on top of the rebased PR #2167 base: - Remove sender field from GetMsg, PutMsg, SubscribeMsg, UpdateMsg, ConnectMsg - Use upstream_addr for routing responses instead of embedded sender fields - Delete transient_manager.rs (no longer needed) - Update freenet-macros code generation for new message structure The routing logic now derives the response target from the connection's observed address (upstream_addr) rather than trusting sender fields in messages. This is more reliable for NAT traversal scenarios. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
This commit applies all wire protocol cleanup changes from PR #2169 on top of the rebased PR #2167 base: - Remove sender field from GetMsg, PutMsg, SubscribeMsg, UpdateMsg, ConnectMsg - Use upstream_addr for routing responses instead of embedded sender fields - Delete transient_manager.rs (no longer needed) - Update freenet-macros code generation for new message structure The routing logic now derives the response target from the connection's observed address (upstream_addr) rather than trusting sender fields in messages. This is more reliable for NAT traversal scenarios. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
This commit applies all wire protocol cleanup changes from PR #2169 on top of the rebased PR #2167 base: - Remove sender field from GetMsg, PutMsg, SubscribeMsg, UpdateMsg, ConnectMsg - Use upstream_addr for routing responses instead of embedded sender fields - Delete transient_manager.rs (no longer needed) - Update freenet-macros code generation for new message structure The routing logic now derives the response target from the connection's observed address (upstream_addr) rather than trusting sender fields in messages. This is more reliable for NAT traversal scenarios. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
This commit applies all wire protocol cleanup changes from PR #2169 on top of the rebased PR #2167 base: - Remove sender field from GetMsg, PutMsg, SubscribeMsg, UpdateMsg, ConnectMsg - Use upstream_addr for routing responses instead of embedded sender fields - Delete transient_manager.rs (no longer needed) - Update freenet-macros code generation for new message structure The routing logic now derives the response target from the connection's observed address (upstream_addr) rather than trusting sender fields in messages. This is more reliable for NAT traversal scenarios. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
This commit applies all wire protocol cleanup changes from PR #2169 on top of the rebased PR #2167 base: - Remove sender field from GetMsg, PutMsg, SubscribeMsg, UpdateMsg, ConnectMsg - Use upstream_addr for routing responses instead of embedded sender fields - Delete transient_manager.rs (no longer needed) - Update freenet-macros code generation for new message structure The routing logic now derives the response target from the connection's observed address (upstream_addr) rather than trusting sender fields in messages. This is more reliable for NAT traversal scenarios. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
This commit applies all wire protocol cleanup changes from PR #2169 on top of the rebased PR #2167 base: - Remove sender field from GetMsg, PutMsg, SubscribeMsg, UpdateMsg, ConnectMsg - Use upstream_addr for routing responses instead of embedded sender fields - Delete transient_manager.rs (no longer needed) - Update freenet-macros code generation for new message structure The routing logic now derives the response target from the connection's observed address (upstream_addr) rather than trusting sender fields in messages. This is more reliable for NAT traversal scenarios. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
This commit applies all wire protocol cleanup changes from PR #2169 on top of the rebased PR #2167 base: - Remove sender field from GetMsg, PutMsg, SubscribeMsg, UpdateMsg, ConnectMsg - Use upstream_addr for routing responses instead of embedded sender fields - Delete transient_manager.rs (no longer needed) - Update freenet-macros code generation for new message structure The routing logic now derives the response target from the connection's observed address (upstream_addr) rather than trusting sender fields in messages. This is more reliable for NAT traversal scenarios. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
This commit applies all wire protocol cleanup changes from PR #2169 on top of the rebased PR #2167 base: - Remove sender field from GetMsg, PutMsg, SubscribeMsg, UpdateMsg, ConnectMsg - Use upstream_addr for routing responses instead of embedded sender fields - Delete transient_manager.rs (no longer needed) - Update freenet-macros code generation for new message structure The routing logic now derives the response target from the connection's observed address (upstream_addr) rather than trusting sender fields in messages. This is more reliable for NAT traversal scenarios. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
This commit applies all wire protocol cleanup changes from PR #2169 on top of the rebased PR #2167 base: - Remove sender field from GetMsg, PutMsg, SubscribeMsg, UpdateMsg, ConnectMsg - Use upstream_addr for routing responses instead of embedded sender fields - Delete transient_manager.rs (no longer needed) - Update freenet-macros code generation for new message structure The routing logic now derives the response target from the connection's observed address (upstream_addr) rather than trusting sender fields in messages. This is more reliable for NAT traversal scenarios. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
Copilot reviewed 29 out of 29 changed files in this pull request and generated no new comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Yes sorry that's what I meant, observed addr. Thanks. |
iduartgomez
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A change I do not see here, but in the configuration, wherever socket addresses are created for the different connections, also typing them strictly to avoid illegal covnersions/usages etc. would be good.
| -> impl Future<Output = ConnResult<()>> + Send; | ||
| fn drop_connection( | ||
| &mut self, | ||
| peer_addr: SocketAddr, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we are still using SocketAddr here
|
|
||
| fn send( | ||
| &self, | ||
| target_addr: SocketAddr, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we are still using SocketAddr here
| } | ||
|
|
||
| /// Upgrades an Unknown joiner to Known once we observe their address. | ||
| pub fn with_observed_address(&self, addr: SocketAddr) -> Self { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
addr: ObservedAddress
|
@iduartgomez Regarding your inline comments about using This PR (#2167) now focuses solely on adding the [AI-assisted - Claude] |
| .await; | ||
| } | ||
| NetMessageV1::Put(ref op) => { | ||
| // Legacy path - no source_addr available |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can this happen? Should we log it? Should we error out?
| .await; | ||
| } | ||
| NetMessageV1::Get(ref op) => { | ||
| // Legacy path - no source_addr available |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can this happen? Should we log it? Should we error out?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, this can happen - it's the current code path used by all operations (Connect/Put/Get/Subscribe/Update) in PR #2167. The NetMessageV1::* handlers all pass None for source_addr as a transitional state.
This legacy path will be removed in PR #2169 when we complete the wire protocol cleanup and switch to connection-based routing everywhere.
For now in #2167, I don't think we need to log it - it's expected behavior during this transition. Once #2169 lands and we switch to ObservedAddr everywhere, these legacy paths will be deleted.
[AI-assisted - Claude]
This PR is the base of a 4-PR stack. The
test_three_node_network_connectivitytest may fail on this PR but passes in #2169 and later.Why: This PR introduces the foundation for connection-based routing, but the wire protocol still embeds
from/senderfields in messages. PR #2169 completes the cleanup by:fromfield fromConnectMsg::Request(sender inferred from transport)senderfield fromConnectMsg::ResponseJoinerenum to usePeerKeyLocationdirectlyvisitedfromVec<PeerKeyLocation>toVec<SocketAddr>These changes are necessary for proper response routing. The test passes in #2169, #2171, and #2172.
Merge order: #2167 → #2169 → #2171 → #2172
Problem
Issue #2164 - Current architecture conflates peer identity with network address, causing NAT traversal failures. Peers embed their own (often incorrect) addresses in messages, and the routing layer relies on these embedded addresses rather than using the transport-layer source address.
Solution
This PR implements Phases 1-4a of #2164:
Phase 1-2: Type System Restructuring
PeerAddrenum (Unknown/Known) for explicit address statePeerKeyLocationto separate identity from addressconnectionsHashMap key fromPeerIdtoSocketAddrLiveTransactionTrackerkey fromPeerIdtoSocketAddrPhase 3: NetworkBridge Refactor
NetworkBridgetrait to useSocketAddrinstead ofPeerIdsource_addrfrom transport layer through message handlingPhase 4a: Connection-Based Routing Foundation
upstream_addrfield to all operations (Get, Put, Subscribe, Update)source_addrparameter toOperation::load_or_initandprocess_messagerewrite_sender_addrhack - no longer needed with real source addresstarget_addrtoOperationResultfor explicit routing decisionsKey Design Principles
pub_keyis identity;SocketAddris "how to reach them"upstream_addrChanges
ring/peer_key_location.rs:PeerAddrenum, restructuredPeerKeyLocationring/live_tx.rs: Changed tracker key toSocketAddrnode/network_bridge.rs: Updated trait to useSocketAddrnode/network_bridge/p2p_protoc.rs: Threadsource_addr, remove address rewritingoperations/*.rs: Addupstream_addr, update signatures forsource_addrmessage.rs: Removerewrite_sender_addrmethodsTesting
Next Steps (PR #2169)
senderfields from wire messages (Get, Put, Subscribe, Update, Connect)skip_listto useSocketAddrPart of #2164
[AI-assisted - Claude]