@@ -11,6 +11,7 @@ use crate::{
1111 message:: { InnerMessage , NetMessage , Transaction } ,
1212 node:: { NetworkBridge , OpManager , PeerId } ,
1313 ring:: { Location , PeerKeyLocation , RingError } ,
14+ transport:: ObservedAddr ,
1415} ;
1516use freenet_stdlib:: {
1617 client_api:: { ContractResponse , ErrorKind , HostResponse } ,
@@ -274,7 +275,11 @@ async fn complete_local_subscription(
274275 key : ContractKey ,
275276) -> Result < ( ) , OpError > {
276277 let subscriber = op_manager. ring . connection_manager . own_location ( ) ;
277- if let Err ( err) = op_manager. ring . add_subscriber ( & key, subscriber. clone ( ) ) {
278+ // Local subscription - no upstream_addr needed since it's our own peer
279+ if let Err ( err) = op_manager
280+ . ring
281+ . add_subscriber ( & key, subscriber. clone ( ) , None )
282+ {
278283 tracing:: warn!(
279284 %key,
280285 tx = %id,
@@ -305,7 +310,7 @@ pub(crate) struct SubscribeOp {
305310 state : Option < SubscribeState > ,
306311 /// The address we received this operation's message from.
307312 /// Used for connection-based routing: responses are sent back to this address.
308- upstream_addr : Option < std :: net :: SocketAddr > ,
313+ upstream_addr : Option < ObservedAddr > ,
309314}
310315
311316impl SubscribeOp {
@@ -359,11 +364,16 @@ impl Operation for SubscribeOp {
359364 }
360365 Ok ( None ) => {
361366 // new request to subscribe to a contract, initialize the machine
367+ tracing:: info!(
368+ tx = %id,
369+ ?source_addr,
370+ "subscribe: load_or_init creating new op with source_addr as upstream_addr"
371+ ) ;
362372 Ok ( OpInitialization {
363373 op : Self {
364374 state : Some ( SubscribeState :: ReceivedRequest ) ,
365375 id,
366- upstream_addr : source_addr, // Connection-based routing: store who sent us this request
376+ upstream_addr : source_addr. map ( ObservedAddr :: new ) , // Connection-based routing: store who sent us this request
367377 } ,
368378 source_addr,
369379 } )
@@ -403,20 +413,19 @@ impl Operation for SubscribeOp {
403413 target : _,
404414 subscriber,
405415 } => {
406- // Fill in subscriber's external address from transport layer if unknown.
407- // This is the key step where the first recipient (gateway) determines the
408- // subscriber's external address from the actual packet source address.
416+ // ALWAYS use the transport-level source address when available.
417+ // This is critical for NAT peers: they may embed a "known" but wrong address
418+ // (e.g., 127.0.0.1:31337 for loopback). The transport address is the only
419+ // reliable way to route responses back through the NAT.
409420 let mut subscriber = subscriber. clone ( ) ;
410- if subscriber. peer_addr . is_unknown ( ) {
411- if let Some ( addr) = source_addr {
412- subscriber. set_addr ( addr) ;
413- tracing:: debug!(
414- tx = %id,
415- %key,
416- subscriber_addr = %addr,
417- "subscribe: filled subscriber address from source_addr"
418- ) ;
419- }
421+ if let Some ( addr) = source_addr {
422+ subscriber. set_addr ( addr) ;
423+ tracing:: debug!(
424+ tx = %id,
425+ %key,
426+ subscriber_addr = %addr,
427+ "subscribe: using transport source_addr for subscriber"
428+ ) ;
420429 }
421430
422431 tracing:: debug!(
@@ -451,9 +460,10 @@ impl Operation for SubscribeOp {
451460 "subscribe: handling RequestSub locally (contract available)"
452461 ) ;
453462
463+ // Use upstream_addr for NAT routing - subscriber may embed wrong address
454464 if op_manager
455465 . ring
456- . add_subscriber ( key, subscriber. clone ( ) )
466+ . add_subscriber ( key, subscriber. clone ( ) , self . upstream_addr )
457467 . is_err ( )
458468 {
459469 tracing:: warn!(
@@ -523,6 +533,13 @@ impl Operation for SubscribeOp {
523533 subscribed : true ,
524534 } ;
525535
536+ tracing:: info!(
537+ tx = %id,
538+ %key,
539+ upstream_addr = ?self . upstream_addr,
540+ "subscribe: creating ReturnSub with upstream_addr"
541+ ) ;
542+
526543 return build_op_result (
527544 self . id ,
528545 None ,
@@ -725,9 +742,10 @@ impl Operation for SubscribeOp {
725742 subscribers_before = ?before_direct,
726743 "subscribe: attempting to register direct subscriber"
727744 ) ;
745+ // Use upstream_addr for NAT routing - subscriber may embed wrong address
728746 if op_manager
729747 . ring
730- . add_subscriber ( key, subscriber. clone ( ) )
748+ . add_subscriber ( key, subscriber. clone ( ) , self . upstream_addr )
731749 . is_err ( )
732750 {
733751 tracing:: warn!(
@@ -875,9 +893,10 @@ impl Operation for SubscribeOp {
875893 subscribers_before = ?before_upstream,
876894 "subscribe: attempting to register upstream link"
877895 ) ;
896+ // upstream_subscriber was stored in op state, no transport address available
878897 if op_manager
879898 . ring
880- . add_subscriber ( key, upstream_subscriber. clone ( ) )
899+ . add_subscriber ( key, upstream_subscriber. clone ( ) , None )
881900 . is_err ( )
882901 {
883902 tracing:: warn!(
@@ -907,7 +926,12 @@ impl Operation for SubscribeOp {
907926 subscribers_before = ?before_provider,
908927 "subscribe: registering provider/subscription source"
909928 ) ;
910- if op_manager. ring . add_subscriber ( key, sender. clone ( ) ) . is_err ( ) {
929+ // Use upstream_addr for NAT routing - sender may embed wrong address
930+ if op_manager
931+ . ring
932+ . add_subscriber ( key, sender. clone ( ) , self . upstream_addr )
933+ . is_err ( )
934+ {
911935 // concurrently it reached max number of subscribers for this contract
912936 tracing:: debug!(
913937 tx = %id,
@@ -964,17 +988,26 @@ fn build_op_result(
964988 id : Transaction ,
965989 state : Option < SubscribeState > ,
966990 msg : Option < SubscribeMsg > ,
967- upstream_addr : Option < std :: net :: SocketAddr > ,
991+ upstream_addr : Option < ObservedAddr > ,
968992) -> Result < OperationResult , OpError > {
969993 // For response messages (ReturnSub), use upstream_addr directly for routing.
970994 // This is more reliable than extracting from the message's target field, which
971995 // may have been looked up from connection_manager (subject to race conditions).
972996 // For forward messages (SeekNode, RequestSub, FetchRouting), use the message's target.
973997 let target_addr = match & msg {
974- Some ( SubscribeMsg :: ReturnSub { .. } ) => upstream_addr,
998+ // Convert ObservedAddr to SocketAddr at the transport boundary
999+ Some ( SubscribeMsg :: ReturnSub { .. } ) => upstream_addr. map ( |a| a. socket_addr ( ) ) ,
9751000 _ => msg. as_ref ( ) . and_then ( |m| m. target_addr ( ) ) ,
9761001 } ;
9771002
1003+ tracing:: info!(
1004+ tx = %id,
1005+ msg_type = ?msg. as_ref( ) . map( |m| std:: any:: type_name_of_val( m) ) ,
1006+ ?upstream_addr,
1007+ ?target_addr,
1008+ "build_op_result: computed target_addr"
1009+ ) ;
1010+
9781011 let output_op = state. map ( |state| SubscribeOp {
9791012 id,
9801013 state : Some ( state) ,
0 commit comments