-
-
Notifications
You must be signed in to change notification settings - Fork 107
fix: use ObservedAddr newtype for NAT routing #2172
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
Closed
sanity
wants to merge
45
commits into
refactor/wire-protocol-cleanup-2164
from
fix/seeding-subscriber-nat-2164
Closed
Changes from all commits
Commits
Show all changes
45 commits
Select commit
Hold shift + click to select a range
edd79da
ci: trigger workflow
sanity 1b6e365
ci: trigger workflow
sanity fba6604
ci: trigger workflow
sanity ed5586f
refactor(ring): restructure PeerKeyLocation to separate identity from…
sanity 104a03f
ci: trigger workflow
sanity 3f9a6f3
refactor: wire protocol cleanup - remove sender fields from messages
sanity 522a964
refactor: migrate PeerKeyLocation field accesses to use new methods
sanity 3d473ed
refactor(ring): restructure PeerKeyLocation to separate identity from…
sanity 4aae58d
refactor: use ObservedAddr newtype for source_addr throughout
sanity 2e57361
ci: trigger workflow
sanity 0ef40bc
fix: resolve post-rebase compilation errors
sanity 76d75c6
refactor: wire protocol cleanup - remove sender fields from messages
sanity 7f6ad28
fix: use upstream_addr for subscribe operation NAT routing
sanity 31a6d9a
fix: route connect responses through upstream_addr
sanity 74f4e77
fix: handle Unknown addresses in get.rs to avoid panics
sanity d1bf045
fix: resolve compilation errors after rebase
sanity 83ce650
ci: trigger workflow
sanity 132e808
ci: trigger workflow
sanity 241ca2f
ci: trigger workflow
sanity bf7f8e6
ci: trigger workflow
sanity be780a5
ci: trigger workflow
sanity e492dba
ci: trigger workflow
sanity 8b6fb72
ci: trigger workflow
sanity 2f1c113
ci: trigger workflow
sanity a2c8cd0
ci: trigger workflow
sanity 4230fb0
ci: trigger workflow
sanity 8e93d31
ci: trigger workflow
sanity b56cbfc
ci: trigger workflow
sanity f2d9b18
ci: trigger workflow
sanity 2e66fb6
ci: trigger workflow
sanity 5de8a58
refactor(ring): restructure PeerKeyLocation to separate identity from…
sanity 6c6f82d
ci: trigger workflow
sanity e84c85f
refactor: wire protocol cleanup - remove sender fields from messages
sanity bd30d98
ci: trigger workflow
sanity cecf6e1
refactor: wire protocol cleanup - remove sender fields from messages
sanity de134e5
ci: trigger workflow
sanity 4764ae9
refactor: wire protocol cleanup - remove sender fields from messages
sanity a9c4e8d
fix: use ObservedAddr newtype for NAT routing in seeding
sanity 86be6f3
fix: change implementation-detail logs from info to debug
sanity 56893c9
fix: correct add_subscriber upstream_addr usage per Claude review
sanity 379ccee
ci: retrigger CI
sanity 741ad39
ci: retrigger CI
sanity 8614d58
fix: resolve compilation errors after rebase
sanity 9db2219
fix: use pub_key() instead of peer() in tracing for acceptors
sanity 8bd39fc
fix: address code review feedback from PR #2172
sanity File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -11,6 +11,7 @@ use crate::{ | |
| message::{InnerMessage, NetMessage, Transaction}, | ||
| node::{NetworkBridge, OpManager, PeerId}, | ||
| ring::{Location, PeerKeyLocation, RingError}, | ||
| transport::ObservedAddr, | ||
| }; | ||
| use freenet_stdlib::{ | ||
| client_api::{ContractResponse, ErrorKind, HostResponse}, | ||
|
|
@@ -274,7 +275,11 @@ async fn complete_local_subscription( | |
| key: ContractKey, | ||
| ) -> Result<(), OpError> { | ||
| let subscriber = op_manager.ring.connection_manager.own_location(); | ||
| if let Err(err) = op_manager.ring.add_subscriber(&key, subscriber.clone()) { | ||
| // Local subscription - no upstream_addr needed since it's our own peer | ||
| if let Err(err) = op_manager | ||
| .ring | ||
| .add_subscriber(&key, subscriber.clone(), None) | ||
| { | ||
| tracing::warn!( | ||
| %key, | ||
| tx = %id, | ||
|
|
@@ -305,7 +310,7 @@ pub(crate) struct SubscribeOp { | |
| state: Option<SubscribeState>, | ||
| /// The address we received this operation's message from. | ||
| /// Used for connection-based routing: responses are sent back to this address. | ||
| upstream_addr: Option<std::net::SocketAddr>, | ||
| upstream_addr: Option<ObservedAddr>, | ||
| } | ||
|
|
||
| impl SubscribeOp { | ||
|
|
@@ -359,11 +364,16 @@ impl Operation for SubscribeOp { | |
| } | ||
| Ok(None) => { | ||
| // new request to subscribe to a contract, initialize the machine | ||
| tracing::debug!( | ||
| tx = %id, | ||
| ?source_addr, | ||
| "subscribe: load_or_init creating new op with source_addr as upstream_addr" | ||
| ); | ||
| Ok(OpInitialization { | ||
| op: Self { | ||
| state: Some(SubscribeState::ReceivedRequest), | ||
| id, | ||
| upstream_addr: source_addr, // Connection-based routing: store who sent us this request | ||
| upstream_addr: source_addr.map(ObservedAddr::new), // Connection-based routing: store who sent us this request | ||
| }, | ||
| source_addr, | ||
| }) | ||
|
|
@@ -403,28 +413,29 @@ impl Operation for SubscribeOp { | |
| target: _, | ||
| subscriber, | ||
| } => { | ||
| // Fill in subscriber's external address from transport layer if unknown. | ||
| // This is the key step where the first recipient (gateway) determines the | ||
| // subscriber's external address from the actual packet source address. | ||
| // ALWAYS use the transport-level source address when available. | ||
| // This is critical for NAT peers: they may embed a "known" but wrong address | ||
| // (e.g., 127.0.0.1:31337 for loopback). The transport address is the only | ||
| // reliable way to route responses back through the NAT. | ||
| let mut subscriber = subscriber.clone(); | ||
| if subscriber.peer_addr.is_unknown() { | ||
| if let Some(addr) = source_addr { | ||
| subscriber.set_addr(addr); | ||
| tracing::debug!( | ||
| tx = %id, | ||
| %key, | ||
| subscriber_addr = %addr, | ||
| "subscribe: filled subscriber address from source_addr" | ||
| ); | ||
| } | ||
| } | ||
|
|
||
| tracing::debug!( | ||
| tx = %id, | ||
| %key, | ||
| subscriber = %subscriber.peer(), | ||
| subscriber_orig = %subscriber.peer(), | ||
| source_addr = ?source_addr, | ||
| "subscribe: processing RequestSub" | ||
| ); | ||
|
|
||
| if let Some(addr) = source_addr { | ||
| subscriber.set_addr(addr); | ||
| tracing::debug!( | ||
| tx = %id, | ||
| %key, | ||
| subscriber_updated = %subscriber.peer(), | ||
| "subscribe: updated subscriber address from transport source" | ||
| ); | ||
| } | ||
| let own_loc = op_manager.ring.connection_manager.own_location(); | ||
|
|
||
| if !matches!( | ||
|
|
@@ -451,9 +462,10 @@ impl Operation for SubscribeOp { | |
| "subscribe: handling RequestSub locally (contract available)" | ||
| ); | ||
|
|
||
| // Use upstream_addr for NAT routing - subscriber may embed wrong address | ||
| if op_manager | ||
| .ring | ||
| .add_subscriber(key, subscriber.clone()) | ||
| .add_subscriber(key, subscriber.clone(), self.upstream_addr) | ||
| .is_err() | ||
| { | ||
| tracing::warn!( | ||
|
|
@@ -520,6 +532,13 @@ impl Operation for SubscribeOp { | |
| subscribed: true, | ||
| }; | ||
|
|
||
| tracing::debug!( | ||
| tx = %id, | ||
| %key, | ||
| upstream_addr = ?self.upstream_addr, | ||
| "subscribe: creating ReturnSub with upstream_addr" | ||
| ); | ||
|
|
||
| return build_op_result( | ||
| self.id, | ||
| None, | ||
|
|
@@ -722,9 +741,13 @@ impl Operation for SubscribeOp { | |
| subscribers_before = ?before_direct, | ||
| "subscribe: attempting to register direct subscriber" | ||
| ); | ||
| // Pass None: subscriber address was already corrected by Gateway at the | ||
| // start of the subscribe flow. Using self.upstream_addr here would | ||
| // incorrectly overwrite with the forwarder's address instead of the | ||
| // original subscriber's Gateway-corrected address. | ||
| if op_manager | ||
| .ring | ||
| .add_subscriber(key, subscriber.clone()) | ||
| .add_subscriber(key, subscriber.clone(), None) | ||
| .is_err() | ||
| { | ||
| tracing::warn!( | ||
|
|
@@ -872,9 +895,10 @@ impl Operation for SubscribeOp { | |
| subscribers_before = ?before_upstream, | ||
| "subscribe: attempting to register upstream link" | ||
| ); | ||
| // upstream_subscriber was stored in op state, no transport address available | ||
| if op_manager | ||
| .ring | ||
| .add_subscriber(key, upstream_subscriber.clone()) | ||
| .add_subscriber(key, upstream_subscriber.clone(), None) | ||
| .is_err() | ||
| { | ||
| tracing::warn!( | ||
|
|
@@ -904,7 +928,15 @@ impl Operation for SubscribeOp { | |
| subscribers_before = ?before_provider, | ||
| "subscribe: registering provider/subscription source" | ||
| ); | ||
| if op_manager.ring.add_subscriber(key, sender.clone()).is_err() { | ||
| // Pass None: sender was already looked up from source_addr (line ~866), | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this is really confussing, whenever you add a subscriber, yolu should know its external address. this shouldn't be optional, and that address should be clearly identified and embedded in the message. |
||
| // so it has the correct transport address. Using self.upstream_addr | ||
| // would incorrectly use the original requester's address instead of | ||
| // the provider's address. | ||
| if op_manager | ||
| .ring | ||
| .add_subscriber(key, sender.clone(), None) | ||
| .is_err() | ||
| { | ||
| // concurrently it reached max number of subscribers for this contract | ||
| tracing::debug!( | ||
| tx = %id, | ||
|
|
@@ -961,17 +993,26 @@ fn build_op_result( | |
| id: Transaction, | ||
| state: Option<SubscribeState>, | ||
| msg: Option<SubscribeMsg>, | ||
| upstream_addr: Option<std::net::SocketAddr>, | ||
| upstream_addr: Option<ObservedAddr>, | ||
| ) -> Result<OperationResult, OpError> { | ||
| // For response messages (ReturnSub), use upstream_addr directly for routing. | ||
| // This is more reliable than extracting from the message's target field, which | ||
| // may have been looked up from connection_manager (subject to race conditions). | ||
| // For forward messages (SeekNode, RequestSub, FetchRouting), use the message's target. | ||
| let target_addr = match &msg { | ||
| Some(SubscribeMsg::ReturnSub { .. }) => upstream_addr, | ||
| // Convert ObservedAddr to SocketAddr at the transport boundary | ||
| Some(SubscribeMsg::ReturnSub { .. }) => upstream_addr.map(|a| a.socket_addr()), | ||
| _ => msg.as_ref().and_then(|m| m.target_addr()), | ||
| }; | ||
|
|
||
| tracing::debug!( | ||
| tx = %id, | ||
| msg_type = ?msg.as_ref().map(|m| std::any::type_name_of_val(m)), | ||
| ?upstream_addr, | ||
| ?target_addr, | ||
| "build_op_result: computed target_addr" | ||
| ); | ||
|
|
||
| let output_op = state.map(|state| SubscribeOp { | ||
| id, | ||
| state: Some(state), | ||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
The comment and usage of
self.upstream_addrare misleading. When handling aRequestSub, this is always the first hop (Gateway receiving from original subscriber). The subscriber's address was already corrected fromsource_addrat line 422, so it no longer embeds a "wrong address". Additionally,self.upstream_addrwas just set to the samesource_addrat line 376 when the operation was initialized.For better code clarity, this should be: