feat(lib): answer FolderContentsRequest with the folder's listing

"Download folder" in SoulseekQt and Nicotine+ asks the sharer for that
one folder (peer code 36) instead of the whole share, and a sharer that
never answers leaves the folder download hanging. The requested folder
now comes back as a FolderContentsResponse (code 37), which carries a
directory listing in the same form a browse does, so the two share one
codec. The browse and folder replies also share one reply helper.
This commit is contained in:
Michel de Graaf
2026-09-07 15:21:42 +02:00
parent 53b32e0201
commit 4839e36be8
7 changed files with 266 additions and 55 deletions
+27 -4
View File
@@ -2,10 +2,10 @@ use crate::actor::{Actor, ActorHandle, ConnectionState};
use crate::client::ClientOperation;
use crate::dispatcher::MessageDispatcher;
use crate::message::peer::{
FileSearchResponse, GetShareFileList, PeerInit, PlaceInQueueRequest,
PlaceInQueueResponse, QueueUploadHandler, SharedDirectory,
SharedFileListResponseHandler, TransferRequest, TransferResponse,
UploadDeniedHandler, UploadFailedHandler,
FileSearchResponse, FolderContentsRequest, GetShareFileList, PeerInit,
PlaceInQueueRequest, PlaceInQueueResponse, QueueUploadHandler,
SharedDirectory, SharedFileListResponseHandler, TransferRequest,
TransferResponse, UploadDeniedHandler, UploadFailedHandler,
};
use crate::message::server::MessageFactory;
use crate::message::{Handlers, Message, MessageReader, MessageType};
@@ -46,6 +46,11 @@ pub enum PeerMessage {
ShareListRequested,
/// A peer we are browsing sent us their shared-file listing (code 5).
ShareListReceived(Vec<SharedDirectory>),
/// A peer asked for one folder of our shares (they sent us code 36).
FolderContentsRequested {
token: u32,
folder: String,
},
/// Offer the queued file to that peer: send an upload TransferRequest.
ServeUpload {
token: u32,
@@ -178,6 +183,7 @@ impl PeerActor {
handlers.register_handler(TransferRequest);
handlers.register_handler(TransferResponse);
handlers.register_handler(GetShareFileList);
handlers.register_handler(FolderContentsRequest);
handlers.register_handler(UploadDeniedHandler);
handlers.register_handler(UploadFailedHandler);
handlers.register_handler(PlaceInQueueRequest);
@@ -273,6 +279,9 @@ impl PeerActor {
PeerMessage::ShareListReceived(directories) => {
self.handle_share_list_received(directories);
}
PeerMessage::FolderContentsRequested { token, folder } => {
self.handle_folder_contents_requested(token, folder);
}
PeerMessage::RequestTransfer(download) => {
let message = MessageFactory::build_transfer_request_message(
&download.filename,
@@ -441,6 +450,20 @@ impl PeerActor {
}
}
fn handle_folder_contents_requested(&self, token: u32, folder: String) {
let requester_key = self.peer_username();
if let Err(e) =
self.client_channel
.send(ClientOperation::FolderContentsRequested {
requester_key,
token,
folder,
})
{
error!("[peer_actor] forward FolderContentsRequested: {}", e);
}
}
fn handle_share_list_received(&self, directories: Vec<SharedDirectory>) {
let username = self.peer_username();
if let Err(e) =