feat(shares): serve queued files to peers over F connections
Implement the upload path so a peer can download our shared files: - fix the mis-coded PlaceInQueueResponse (43 -> 44) and add a real QueueUpload handler (code 43) -> PeerMessage::IncomingQueueUpload; - the peer actor forwards it as ClientOperation::QueueUpload; the client looks the file up in its shares, mints an upload token (high half of the token space, disjoint from md5 download tokens), and offers it via ServeUpload -> build_upload_transfer_request (peer code 40, direction=upload); - a TransferResponse for one of our serving tokens is handled by a surgical early-return that emits StartUpload, leaving the download path untouched; - StartUpload resolves the downloader's address (GetPeerAddress, cached) and streams the file via a new peer::upload_peer::serve_file over an F connection. Tested: build_upload_transfer_request decodes via the production Transfer parser; serve_file streams a file correctly over a loopback F connection.
This commit is contained in:
@@ -2,6 +2,7 @@ mod file_search_response;
|
||||
mod get_share_file_list;
|
||||
mod peer_init;
|
||||
mod place_in_queue_response;
|
||||
mod queue_upload;
|
||||
mod transfer_request;
|
||||
mod transfer_response;
|
||||
mod upload_failed;
|
||||
@@ -13,6 +14,7 @@ pub use file_search_response::{
|
||||
pub use get_share_file_list::GetShareFileList;
|
||||
pub use peer_init::PeerInit;
|
||||
pub use place_in_queue_response::PlaceInQueueResponse;
|
||||
pub use queue_upload::QueueUploadHandler;
|
||||
pub use transfer_request::TransferRequest;
|
||||
pub use transfer_response::TransferResponse;
|
||||
pub use upload_failed::UploadFailedHandler;
|
||||
|
||||
@@ -8,7 +8,7 @@ pub struct PlaceInQueueResponse;
|
||||
|
||||
impl MessageHandler<PeerMessage> for PlaceInQueueResponse {
|
||||
fn get_code(&self) -> u8 {
|
||||
43
|
||||
44
|
||||
}
|
||||
|
||||
fn handle(&self, message: &mut Message, sender: Sender<PeerMessage>) {
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
use crate::{
|
||||
message::{Message, MessageHandler},
|
||||
peer::PeerMessage,
|
||||
};
|
||||
use std::sync::mpsc::Sender;
|
||||
|
||||
/// A peer asking to download one of our shared files (peer code 43).
|
||||
pub struct QueueUploadHandler;
|
||||
|
||||
impl MessageHandler<PeerMessage> for QueueUploadHandler {
|
||||
fn get_code(&self) -> u8 {
|
||||
43
|
||||
}
|
||||
|
||||
fn handle(&self, message: &mut Message, sender: Sender<PeerMessage>) {
|
||||
let filename = message.read_string();
|
||||
let _ = sender.send(PeerMessage::IncomingQueueUpload(filename));
|
||||
}
|
||||
}
|
||||
@@ -142,6 +142,23 @@ impl MessageFactory {
|
||||
.write_string(filename)
|
||||
.clone()
|
||||
}
|
||||
/// A TransferRequest (peer code 40) initiating an *upload*: we offer a file
|
||||
/// to a peer who queued it, quoting our transfer token and its size.
|
||||
#[must_use]
|
||||
pub fn build_upload_transfer_request(
|
||||
filename: &str,
|
||||
token: u32,
|
||||
size: u64,
|
||||
) -> Message {
|
||||
Message::new()
|
||||
.write_int32(40)
|
||||
.write_int32(1) // direction: upload
|
||||
.write_int32(token)
|
||||
.write_string(filename)
|
||||
.write_int64(size)
|
||||
.clone()
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn build_transfer_response_message(transfer: Transfer) -> Message {
|
||||
Message::new()
|
||||
@@ -199,6 +216,21 @@ fn test_build_login_message() {
|
||||
assert_eq!(expect, message.get_data());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_build_upload_transfer_request() {
|
||||
use crate::types::Transfer;
|
||||
let message =
|
||||
MessageFactory::build_upload_transfer_request("song.mp3", 555, 4096);
|
||||
// Decode via the production Transfer parser (dispatcher starts at offset 8).
|
||||
let mut decoded = Message::new_with_data(message.get_buffer());
|
||||
decoded.set_pointer(8);
|
||||
let transfer = Transfer::new_from_message(&mut decoded);
|
||||
assert_eq!(transfer.direction, 1); // upload
|
||||
assert_eq!(transfer.token, 555);
|
||||
assert_eq!(transfer.filename, "song.mp3");
|
||||
assert_eq!(transfer.size, 4096);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_build_peer_init_message() {
|
||||
use crate::peer::ConnectionType;
|
||||
|
||||
Reference in New Issue
Block a user