feat: direct peer connections — download() connects to unconnected peers
Implement the DIRECT connection-initiation mode so a download can target a peer the client is not already connected to: - Fix the outbound peer handshake. on_connection_established sent build_watch_user() (a server WatchUser message, wrongly framed with get_data()) for outbound connections; it now sends a proper length-prefixed PeerInit (peer code 1) with our own username. own_username is plumbed in via PeerRegistry -> PeerActor; inbound peers (outbound=false) are unchanged. - download() now auto-connects: if there is no control connection to the peer it sends GetPeerAddress and defers the QueueUpload until the outbound stream handshakes, signalled by a new ClientOperation::PeerConnected. A never- connected client still resolves the download to Failed (unit test). - Add Client::connect_peer(username) to open/pre-warm a control connection. Verified end to end against soulfind: a_file_downloads_from_a_peer_via_direct_connection logs a mock peer into the server, advertises its port via SetWaitPort, and the client resolves the address, dials it, and downloads the file — bytes match. The F-serve leg is shared with the passive-download mock.
This commit is contained in:
@@ -15,6 +15,7 @@ pub struct PeerRegistry {
|
||||
peers: Arc<Mutex<HashMap<String, ActorHandle<PeerMessage>>>>,
|
||||
actor_system: Arc<ActorSystem>,
|
||||
client_channel: Sender<ClientOperation>,
|
||||
own_username: String,
|
||||
}
|
||||
|
||||
impl PeerRegistry {
|
||||
@@ -22,11 +23,13 @@ impl PeerRegistry {
|
||||
pub fn new(
|
||||
actor_system: Arc<ActorSystem>,
|
||||
client_channel: Sender<ClientOperation>,
|
||||
own_username: String,
|
||||
) -> Self {
|
||||
Self {
|
||||
peers: Arc::new(Mutex::new(HashMap::new())),
|
||||
actor_system,
|
||||
client_channel,
|
||||
own_username,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,8 +41,13 @@ impl PeerRegistry {
|
||||
) -> Result<ActorHandle<PeerMessage>, String> {
|
||||
let username = peer.username.clone();
|
||||
|
||||
let actor =
|
||||
PeerActor::new(peer, stream, reader, self.client_channel.clone());
|
||||
let actor = PeerActor::new(
|
||||
peer,
|
||||
stream,
|
||||
reader,
|
||||
self.client_channel.clone(),
|
||||
self.own_username.clone(),
|
||||
);
|
||||
|
||||
let handle =
|
||||
self.actor_system.spawn_with_handle(actor, |actor, handle| {
|
||||
@@ -157,6 +165,7 @@ impl Clone for PeerRegistry {
|
||||
peers: self.peers.clone(),
|
||||
actor_system: self.actor_system.clone(),
|
||||
client_channel: self.client_channel.clone(),
|
||||
own_username: self.own_username.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user