Skip to content

Conversation

@sanity
Copy link
Collaborator

@sanity sanity commented Nov 28, 2025

Problem

Phase 4 Part 2 of #2164 - The Connect protocol still has embedded from/sender fields in messages, even though we now have source_addr from the transport layer available for routing.

Solution

Remove envelope routing fields from Connect messages, using connection-based routing like the other operations (Get, Put, Subscribe, Update):

  1. Remove from from ConnectMsg::Request - Use transport layer source_addr instead
  2. Remove sender from ConnectMsg::Response - Response routing uses stored upstream_addr
  3. Change visited to Vec<SocketAddr> - Track visited addresses instead of full PeerKeyLocation
  4. Change RelayState.upstream to upstream_addr: SocketAddr - Store socket address for response routing

Key Distinction

The Connect protocol still needs embedded addresses for the joiner and acceptor:

  • ConnectRequest.joiner - The joiner's address for NAT hole-punching
  • ConnectResponse.acceptor - The acceptor's address for direct connection

These are payload data, not routing metadata. The difference:

  • Routing (removed): "who sent this packet" - use transport layer
  • Payload (kept): "who should I connect to" - needed for NAT hole-punching

Changes

  • operations/connect.rs: Remove from/sender fields, update relay logic
  • p2p_protoc.rs: Update extract_sender_from_message to return None for Connect

Testing

  • All 9 connect module unit tests pass
  • Docker NAT test: 100% connectivity (gateway + 2 NAT peers)

Stack

Stacked on #2167 (adds upstream_addr and source_addr threading)

[AI-assisted - Claude]

Copy link
Contributor

Copilot AI left a 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 removes embedded routing metadata (from/sender fields) from Connect protocol messages, transitioning to connection-based routing using the transport layer's source_addr. This is part of a larger refactoring effort (Phase 4 Part 2 of #2164) to eliminate redundant routing information from messages while preserving payload data needed for NAT hole-punching.

Key changes:

  • Removed from field from ConnectMsg::Request and sender field from ConnectMsg::Response, using source_addr from transport layer for routing
  • Changed visited tracking from Vec<PeerKeyLocation> to Vec<SocketAddr> for simpler address-based loop detection
  • Updated RelayState.upstream to upstream_addr: SocketAddr for response routing
  • Added get_peer_location_by_addr() method to ConnectionManager for reverse lookups when full peer info is needed
  • Updated extract_sender_from_message() to return None for Connect/Get/Put/Subscribe/Update messages since they now use connection-based routing

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
crates/core/src/operations/connect.rs Core changes: removed from/sender fields, changed visited to Vec<SocketAddr>, updated relay logic to use upstream_addr, and modified tests
crates/core/src/node/network_bridge/p2p_protoc.rs Updated sender extraction functions to return None for messages using connection-based routing
crates/core/src/ring/connection_manager.rs Added get_peer_location_by_addr() helper method for reverse peer lookups from socket addresses
crates/core/src/operations/get.rs Updated to use source_addr for sender lookups instead of embedded sender field
crates/core/src/operations/put.rs Updated to use source_addr for sender lookups and added origin address filling logic
crates/core/src/operations/subscribe.rs Updated to use source_addr for sender lookups and added subscriber address filling logic
crates/core/src/operations/update.rs Updated to use source_addr for sender lookups instead of embedded sender field
crates/core/src/tracing/mod.rs Updated event logging to handle removed sender fields with placeholders

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +286 to +287
// Note: sender no longer embedded in message - use connection-based routing
target: target.clone(), // Placeholder - actual sender from source_addr
Copy link

Copilot AI Nov 29, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The target field is being used for both requester and target, which makes the logged data incorrect. In the original code, sender contained the peer that sent the ReturnGet message (the node that has the contract), and target was the requester. Now both are set to target, which means both the requester and the responder are logged as the same peer.

Since sender information is no longer embedded in the message, this logging should be updated to use connection-based routing data or removed/marked as unavailable if source_addr is not accessible in this context.

Suggested change
// Note: sender no longer embedded in message - use connection-based routing
target: target.clone(), // Placeholder - actual sender from source_addr
// Sender information is unavailable; set to None to avoid incorrect logging
target: None,

Copilot uses AI. Check for mistakes.
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Acknowledged - this is a documented limitation of the wire protocol simplification. The EventKind types use non-optional PeerKeyLocation, so setting to None would require a breaking type change.

The comments document this as a known limitation: "Note: sender no longer embedded in message - use connection-based routing". The placeholder ensures the data structure is complete for tracing purposes, even though the sender value isn't semantically accurate.

A follow-up enhancement could pass source_addr into the tracing context to get accurate sender info, but that's beyond the scope of this cleanup PR.

[AI-assisted - Claude]

Comment on lines +297 to +298
// Note: sender no longer embedded in message - use connection-based routing
at: target.clone(), // Placeholder - actual sender from source_addr
Copy link

Copilot AI Nov 29, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The at field is being set to target, which is incorrect. In the original code, sender contained the peer that accepted the subscription (the node that has the contract), and target was the requester/subscriber. Now at is set to the subscriber instead of the node that accepted the subscription.

Since sender information is no longer embedded in the message, this logging should be updated to use connection-based routing data or removed/marked as unavailable if source_addr is not accessible in this context.

Suggested change
// Note: sender no longer embedded in message - use connection-based routing
at: target.clone(), // Placeholder - actual sender from source_addr
// Note: sender no longer embedded in message - sender unavailable in this context
at: None, // Sender unavailable - see comment above

Copilot uses AI. Check for mistakes.
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above - documented limitation with placeholder. The EventKind types don't support optional fields without a breaking change. A future enhancement could thread source_addr through to this context.

[AI-assisted - Claude]

Comment on lines +328 to +329
// Note: sender no longer embedded in message - use connection-based routing
sender: upstream.clone(), // Placeholder - actual sender from source_addr
Copy link

Copilot AI Nov 29, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The sender field is being set to upstream instead of the actual sender. In the original code, the sender field contained the peer that emitted the broadcast. The upstream field represents the peer we're broadcasting back to (the requester), not the peer that sent us this broadcast message.

Since sender information is no longer embedded in the message, this logging should be updated to use connection-based routing data or removed/marked as unavailable if source_addr is not accessible in this context.

Suggested change
// Note: sender no longer embedded in message - use connection-based routing
sender: upstream.clone(), // Placeholder - actual sender from source_addr
// Note: sender no longer embedded in message - sender unavailable in this context
sender: None, // Sender unavailable - not present in message

Copilot uses AI. Check for mistakes.
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same limitation - placeholder with documented comment. The accurate sender would come from source_addr which isn't available in this context yet.

[AI-assisted - Claude]

Comment on lines +342 to +343
// Note: sender no longer embedded in message - use connection-based routing
target: target.clone(), // Placeholder - actual sender from source_addr
Copy link

Copilot AI Nov 29, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The target field is being used for both requester and target, which makes the logged data incorrect. In the original code, sender contained the peer that sent the BroadcastTo message, and target was the recipient. Now both are set to target, which means both the sender and receiver are logged as the same peer.

Since sender information is no longer embedded in the message, this logging should be updated to use connection-based routing data or removed/marked as unavailable if source_addr is not accessible in this context.

Copilot uses AI. Check for mistakes.
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same pattern - documented placeholder. These tracing fields would need source_addr threaded through for accurate values.

[AI-assisted - Claude]

Comment on lines 1018 to 1043
impl Contains<PeerId> for SkipListWithSelf<'_> {
fn has_element(&self, target: PeerId) -> bool {
&target == self.self_peer || self.visited.iter().any(|p| p.peer() == target)
if &target == self.self_peer {
return true;
}
// Check if any visited address belongs to this peer
for addr in self.visited {
if let Some(peer_id) = self.conn_manager.get_peer_by_addr(*addr) {
if peer_id == target {
return true;
}
}
}
false
}
Copy link

Copilot AI Nov 29, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The SkipListWithSelf implementation has a potential issue where visited addresses that don't map to known peers (due to disconnections or race conditions) will not be excluded. When get_peer_by_addr() returns None, the loop continues but doesn't track that we've seen this address before.

This could allow a peer to be selected as a forwarding target even though their address is in the visited list, if they've disconnected and reconnected or if there's a race condition in the connection tracking.

Consider keeping track of the visited addresses themselves in addition to looking up peer IDs, or at least documenting this limitation.

Copilot uses AI. Check for mistakes.
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Valid observation about the race condition, but this is benign in practice:

  1. If a peer disconnected, they won't be selected as a forwarding target anyway since routing requires an active connection
  2. If they've reconnected at the same address, get_peer_by_addr() will find them
  3. If they've reconnected at a different address, that's a different connection - it's reasonable to route through them

The visited list tracks routing history to prevent loops. If we can't resolve an address to a current peer, we skip it - which is correct since we can't route to a disconnected peer regardless.

I'll add a comment documenting this behavior.

[AI-assisted - Claude]

@sanity sanity force-pushed the refactor/connection-based-routing-2164 branch from 345e3e7 to 2e39f69 Compare November 29, 2025 19:28
sanity added a commit that referenced this pull request Nov 29, 2025
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]>
@sanity sanity force-pushed the refactor/wire-protocol-cleanup-2164 branch from 324bd29 to ed93d91 Compare November 29, 2025 19:47
sanity added a commit that referenced this pull request Nov 29, 2025
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]>
@sanity sanity force-pushed the refactor/wire-protocol-cleanup-2164 branch from cfee166 to 945fdb3 Compare November 29, 2025 22:38
sanity added a commit that referenced this pull request Nov 29, 2025
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]>
@sanity sanity force-pushed the refactor/wire-protocol-cleanup-2164 branch from 945fdb3 to 642a8d4 Compare November 29, 2025 23:33
sanity added a commit that referenced this pull request Nov 29, 2025
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]>
@sanity sanity force-pushed the refactor/wire-protocol-cleanup-2164 branch from 642a8d4 to a2d4cfe Compare November 29, 2025 23:42
sanity added a commit that referenced this pull request Nov 29, 2025
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]>
sanity added a commit that referenced this pull request Nov 30, 2025
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]>
@sanity sanity force-pushed the refactor/wire-protocol-cleanup-2164 branch from a2d4cfe to 3230675 Compare November 30, 2025 00:13
sanity added a commit that referenced this pull request Nov 30, 2025
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]>
sanity added a commit that referenced this pull request Nov 30, 2025
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]>
@sanity
Copy link
Collaborator Author

sanity commented Nov 30, 2025

@claude please do a code review of this PR. This is part 2 of a 4-PR stack - it cleans up the wire protocol by removing embedded sender fields now that routing uses transport-layer source addresses.

@claude
Copy link

claude bot commented Nov 30, 2025

Claude finished @sanity's task —— View job


Code Review Complete

I've reviewed PR #2169, which removes embedded from/sender fields from Connect protocol messages as part of the wire protocol cleanup effort. Here are my findings:


Strengths

  1. Clean Architectural Improvement

    • Successfully eliminates redundant routing metadata from Connect messages
    • Properly leverages transport layer source_addr for routing, following the same pattern as Get/Put/Subscribe/Update operations
    • Reduces message size and protocol complexity
  2. Correct Distinction Between Routing and Payload

    • The PR correctly preserves joiner and acceptor fields in the payload (needed for NAT hole-punching)
    • Only removes the routing-level from/sender fields
    • This distinction is well-documented in the PR description and code comments
  3. Comprehensive Implementation

    • All affected operations (Connect, Get, Put, Subscribe, Update) updated consistently
    • extract_sender_from_message() correctly returns None for all connection-based routing operations (connect.rs:2664-2678)
    • New get_peer_location_by_addr() helper added to ConnectionManager for reverse lookups when full peer info is needed (connection_manager.rs:348-374)
  4. Good Test Coverage

  5. Clear Documentation

    • Code comments explain the change rationale
    • PR description provides excellent context about the distinction between routing and payload

⚠️ Issues Identified

1. Tracing/Logging Placeholders - Acknowledged Limitation

Location: crates/core/src/tracing/mod.rs:287, 298, 329, 343

The PR acknowledges this limitation in review responses: sender information is no longer embedded in messages, so tracing uses placeholder values (often using target for both sender and receiver). This creates incorrect/misleading log data for debugging.

Current state:

  • Line 287: target used for both requester and target in Get ReturnGet event
  • Line 298: target used for at field in Subscribe ReturnSub event
  • Line 329: upstream used as sender in Update Broadcasting event
  • Line 343: target used for both sender and receiver in Update BroadcastTo event

Recommendation:

  • Short term (this PR): The placeholder approach is acceptable if documented as a known limitation
  • Follow-up task: Thread source_addr through to tracing contexts to restore accurate sender logging OR update EventKind types to make sender fields Option<PeerKeyLocation> (breaking change)
  • Consider adding a TODO/FIXME comment referencing a follow-up issue number

2. Visited List Race Condition - Benign but Worth Documenting

Location: crates/core/src/operations/connect.rs:1043 (copilot review comment)

The SkipListWithSelf implementation doesn't track visited addresses that fail peer lookup:

// Check if any visited address belongs to this peer
for addr in self.visited {
    if let Some(peer_id) = self.conn_manager.get_peer_by_addr(*addr) {
        if peer_id == target {
            return true;
        }
    }
    // Missing: no tracking for addresses that return None
}

Analysis:
Your response correctly notes this is benign in practice:

  • Disconnected peers won't be selected anyway (no active connection)
  • Peers that reconnected at the same address will be found
  • Peers at different addresses are legitimately different routing options

Recommendation:
Add a comment documenting this behavior as you mentioned in your response. Something like:

// Note: If get_peer_by_addr() returns None (peer disconnected or race condition),
// we skip checking that address. This is safe because:
// 1. Disconnected peers can't be selected for routing anyway
// 2. Reconnected peers at the same addr will be found
// 3. Peers at different addrs are legitimately different connections

3. Minor: Connection Manager Lookup Performance

Location: connection_manager.rs:348-374

The new get_peer_location_by_addr() method does a linear scan through all connections:

for conns in connections.values() {
    for conn in conns {
        if conn.location.addr() == addr {
            return Some(conn.location.clone());
        }
    }
}

Impact: This is called on every message receive path for connection-based routing operations.

Recommendation:

  • For this PR: Accept as-is - peer counts are small enough that linear scan is fine
  • Future optimization: Consider adding a reverse index addr_to_location: HashMap<SocketAddr, PeerKeyLocation> in ConnectionManager if profiling shows this is a hotspot

📋 Code Quality Observations

  1. Test Quality: The regression test for ConnectResponse sent to joiner's private address instead of observed external address #2141 (lines 1593-1660) is excellent - it directly tests the observed address vs private address distinction for NAT scenarios

  2. Code Deletion: Nice to see 1367 deletions vs 821 additions - the refactoring genuinely simplifies the codebase

  3. Consistent Pattern: The change follows the same connection-based routing pattern across all operations, making the codebase more consistent


🎯 Recommendations

  1. Merge as-is with follow-up: The tracing placeholder limitation is acceptable for a wire protocol cleanup PR. Create a follow-up issue to track the tracing improvement.

  2. 📝 Add documentation comment: Add the race condition comment suggested in issue NAT traversal #2 above to connect.rs:1043

  3. 🔍 Follow-up issue: Create an issue to track threading source_addr through to tracing contexts for accurate sender logging


Summary

This is a well-executed refactoring that successfully removes redundant routing metadata while preserving necessary NAT hole-punching information. The tracing placeholder limitation is a documented trade-off that can be addressed in follow-up work. The code is well-tested, follows consistent patterns, and simplifies the protocol.

Overall assessment:Approve with minor follow-up documentation improvements


@sanity sanity force-pushed the refactor/connection-based-routing-2164 branch from 58459ac to 51c0ddb Compare November 30, 2025 22:19
@sanity sanity force-pushed the refactor/wire-protocol-cleanup-2164 branch from 6a99400 to 3dd47e0 Compare November 30, 2025 22:19
sanity and others added 2 commits November 30, 2025 20:35
The acceptor's PeerAddr is intentionally Unknown (NAT scenario) since
the local peer doesn't know its external address yet. Use pub_key()
instead of peer() to avoid panics on unknown addresses.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
- Remove get_known_locations fallback (intentionally removed in base PR)
- Use peer.addr() instead of peer.peer() for DropConnection (expects SocketAddr)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
@sanity sanity force-pushed the refactor/wire-protocol-cleanup-2164 branch from 5e9e11f to 43f4f4a Compare December 1, 2025 02:35
sanity added a commit that referenced this pull request Dec 1, 2025
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]>
sanity added a commit that referenced this pull request Dec 1, 2025
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]>
sanity added a commit that referenced this pull request Dec 1, 2025
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]>
sanity added a commit that referenced this pull request Dec 1, 2025
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]>
sanity added a commit that referenced this pull request Dec 1, 2025
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]>
sanity added a commit that referenced this pull request Dec 1, 2025
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]>
sanity added a commit that referenced this pull request Dec 1, 2025
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]>
sanity added a commit that referenced this pull request Dec 1, 2025
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]>
sanity added a commit that referenced this pull request Dec 1, 2025
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]>
sanity added a commit that referenced this pull request Dec 1, 2025
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]>
sanity added a commit that referenced this pull request Dec 1, 2025
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]>
sanity and others added 3 commits November 30, 2025 21:23
Moves port release to immediately before node binding instead of before
config building. This keeps ports reserved longer, reducing (though not
eliminating) the race window where another process could grab the port.

The fundamental race window cannot be eliminated without either:
1. SO_REUSEADDR on both reservation and node sockets
2. Dedicated port ranges for CI (sysctl ip_local_reserved_ports)
3. Network namespace isolation

This change provides marginal improvement for self-hosted runners where
port competition is higher.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
The test framework has an unavoidable race between releasing reserved
ports and nodes binding to them. On busy self-hosted runners, another
process may occasionally grab the port in this window.

This is a transient issue - retriggering typically succeeds. Complete
fixes would require SO_REUSEADDR, sysctl port ranges, network namespace
isolation, or test framework restructuring.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
@sanity sanity requested a review from Copilot December 1, 2025 05:17
Copilot finished reviewing on behalf of sanity December 1, 2025 05:19
Copy link
Contributor

Copilot AI left a 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 20 out of 21 changed files in this pull request and generated 5 comments.

Files not reviewed (1)
  • tests/test-app-1/package-lock.json: Language not supported

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +1427 to +1428
// visited now contains SocketAddr
assert!(request.visited.contains(&joiner.addr()));
Copy link

Copilot AI Dec 1, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] The comment states "visited now contains SocketAddr" but the assertion only checks if joiner.addr() is present. The comment at line 136 in connect.rs states that visited is a "Simple visited set to avoid trivial loops (addresses of peers that have seen this request)."

However, there's a potential issue: if a peer changes its address (e.g., due to reconnection or NAT rebinding), the visited list would not recognize it as the same peer, potentially allowing loops. Consider if this is the intended behavior or if additional peer identity checking is needed.

Copilot uses AI. Check for mistakes.
Comment on lines +1475 to +1476
// Give extra time for peer to connect to gateway
tokio::time::sleep(Duration::from_secs(5)).await;
Copy link

Copilot AI Dec 1, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] The sleep duration of 5 seconds was added here with the comment "Give extra time for peer to connect to gateway". This appears to be compensating for the removal of the wait_for_connections feature that was deleted in this PR.

However, this introduces a fixed delay that may be:

  1. Too short in some environments (causing test flakiness)
  2. Too long in fast environments (wasting time)

Consider whether this test needs better synchronization logic or if the 5-second sleep is a temporary workaround for removed functionality.

Copilot uses AI. Check for mistakes.
Comment on lines 88 to 104
if stable_rounds >= 3 && current_connections > 0 {
tracing::info!(
"Connection count stable at {}, triggering active peer discovery",
current_connections
);

// Trigger the connection maintenance task to actively look for more peers
// In small networks, we want to be more aggressive
for _ in 0..3 {
// Yield before each connection attempt to prevent blocking other tasks
tokio::task::yield_now().await;

if let Err(e) = self.trigger_connection_maintenance().await {
tracing::warn!("Failed to trigger connection maintenance: {}", e);
}
tokio::time::sleep(Duration::from_millis(100)).await;
}
Copy link

Copilot AI Dec 1, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] The trigger_connection_maintenance method is called up to 3 times in a loop (lines 96-104) when connection count is stable. Each invocation creates a new ConnectOp and transaction. If multiple nodes are doing this simultaneously in a small network, this could create a connection storm.

Consider:

  1. Adding a cooldown period between maintenance triggers
  2. Limiting the number of concurrent connection maintenance operations
  3. Adding logging to track how often this aggressive discovery is triggered in practice

Copilot uses AI. Check for mistakes.
Comment on lines +4832 to +4834
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz",
"integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==",
Copy link

Copilot AI Dec 1, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The node-forge package is being downgraded from version 1.3.2 to 1.3.1. This appears unrelated to the PR's purpose (removing from/sender fields from ConnectMsg). Consider reverting this change or explaining why it's necessary in a separate commit.

Additionally, the removal of the "license" field at line 4836 may be unintentional.

Suggested change
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz",
"integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==",
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.2.tgz",
"integrity": "sha512-+Q6Qn6Qn1Qn6Qn6Qn6Qn6Qn6Qn6Qn6Qn6Qn6Qn6Qn6Qn6Qn6Qn6Qn6Qn6Qn6Qn6Qn6Qn6Qn6Qn6Qn6Q==",
"license": "BSD-3-Clause",

Copilot uses AI. Check for mistakes.
Comment on lines 140 to 143
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.2.tgz",
"integrity": "sha512-n7s51eWdaWZ3vGT2tD4T7J6eJs3QoBXydv7vkUM06Bf1cbVD2Kc2UrkzhiQwobfV7NwOnQXYL7UBJ5VPU+RGoQ==",
"dev": true,
"peer": true,
"dependencies": {
Copy link

Copilot AI Dec 1, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Multiple "peer": true entries are being removed throughout the package-lock.json file. This change appears unrelated to the PR's stated purpose of refactoring ConnectMsg routing. These package-lock changes should either be:

  1. Reverted if unintentional
  2. Moved to a separate PR if intentional
  3. Explained in the PR description

The changes appear to be automated npm updates rather than manual modifications related to the routing refactor.

Copilot uses AI. Check for mistakes.
Base automatically changed from refactor/connection-based-routing-2164 to main December 2, 2025 00:11
@sanity
Copy link
Collaborator Author

sanity commented Dec 2, 2025

Closing: changes superseded by PRs #2174 and #2175 which have been rebased cleanly on main. [AI-assisted - Claude]

@sanity sanity closed this Dec 2, 2025
@sanity sanity deleted the refactor/wire-protocol-cleanup-2164 branch December 2, 2025 00:17
sanity added a commit that referenced this pull request Dec 2, 2025
Consolidates approved changes from PRs #2169 and #2171:

- Remove ObservedAddr in favor of std::net::SocketAddr
- Add PeerAddr enum to explicitly represent known/unknown addresses
- Update PeerKeyLocation to use PeerAddr for NAT scenarios
- Clean up wire protocol types for address handling
- Remove unused transient_manager module

This is part of the larger #2164 effort to simplify peer identity.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
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.

3 participants