Back to Site
Loading...
Searching...
No Matches
file_transfer.h
Go to the documentation of this file.
1#pragma once
2
3#include "socket.h"
4#include "json.hpp"
5#include <string>
6#include <vector>
7#include <functional>
8#include <memory>
9#include <mutex>
10#include <unordered_map>
11#include <atomic>
12#include <chrono>
13#include <thread>
14#include <queue>
15#include <condition_variable>
16
17namespace librats {
18
19// Forward declaration
20class RatsClient;
21
26 PENDING, // Transfer queued but not started
27 STARTING, // Transfer initialization in progress
28 IN_PROGRESS, // Transfer actively sending/receiving chunks
29 PAUSED, // Transfer temporarily paused
30 COMPLETED, // Transfer completed successfully
31 FAILED, // Transfer failed due to error
32 CANCELLED, // Transfer cancelled by user
33 RESUMING // Transfer resuming from interruption
34};
35
40 SENDING, // We are sending the file
41 RECEIVING // We are receiving the file
42};
43
44// Note: Compression removed as requested - only binary chunks needed
45
49struct FileChunk {
50 std::string transfer_id; // Unique transfer identifier
51 uint64_t chunk_index; // Sequential chunk number (0-based)
52 uint64_t total_chunks; // Total number of chunks in transfer
53 uint64_t chunk_size; // Size of this specific chunk
54 uint64_t file_offset; // Offset in the original file
55 std::vector<uint8_t> data; // Chunk data payload
56 std::string checksum; // SHA256 checksum of chunk data
57
60};
61
66 std::string filename; // Original filename
67 std::string relative_path; // Relative path within directory structure
68 uint64_t file_size; // Total file size in bytes
69 uint64_t last_modified; // Last modification timestamp
70 std::string mime_type; // MIME type of the file
71 std::string checksum; // Full file checksum
72
74};
75
80 std::string directory_name; // Directory name
81 std::string relative_path; // Relative path
82 std::vector<FileMetadata> files; // Files in this directory level
83 std::vector<DirectoryMetadata> subdirectories; // Nested directories
84
85 // Calculate total transfer size
86 uint64_t get_total_size() const;
87
88 // Get total file count
89 size_t get_total_file_count() const;
90};
91
96 std::string transfer_id; // Transfer identifier
97 std::string peer_id; // Peer we're transferring with
98 FileTransferDirection direction; // Send or receive
99 FileTransferStatus status; // Current status
100
101 // File information
102 std::string filename; // File being transferred
103 std::string local_path; // Local file path
104 uint64_t file_size; // Total file size
105
106 // Progress tracking
107 uint64_t bytes_transferred; // Bytes completed
108 uint64_t total_bytes; // Total bytes to transfer
109 uint32_t chunks_completed; // Chunks successfully transferred
110 uint32_t total_chunks; // Total chunks in transfer
111
112 // Performance metrics
113 std::chrono::steady_clock::time_point start_time; // Transfer start time
114 std::chrono::steady_clock::time_point last_update; // Last progress update
115 double transfer_rate_bps; // Current transfer rate (bytes/second)
116 double average_rate_bps; // Average transfer rate since start
117 std::chrono::milliseconds estimated_time_remaining; // ETA
118
119 // Error information
120 std::string error_message; // Error details if failed
121 uint32_t retry_count; // Number of retries attempted
122
132
133 // Calculate completion percentage (0.0 to 100.0)
135 if (total_bytes == 0) return 0.0;
136 return (static_cast<double>(bytes_transferred) / total_bytes) * 100.0;
137 }
138
139 // Calculate elapsed time
140 std::chrono::milliseconds get_elapsed_time() const {
141 return std::chrono::duration_cast<std::chrono::milliseconds>(
142 std::chrono::steady_clock::now() - start_time);
143 }
144
145 // Update transfer rate calculations
146 void update_transfer_rates(uint64_t new_bytes_transferred);
147};
148
153 uint32_t chunk_size; // Size of each chunk (default: 64KB)
154 uint32_t max_concurrent_chunks; // Max chunks in flight (default: 4)
155 uint32_t max_retries; // Max retry attempts per chunk (default: 3)
156 uint32_t timeout_seconds; // Timeout per chunk (default: 30)
157 bool verify_checksums; // Verify chunk checksums (default: true)
158 bool allow_resume; // Allow resuming interrupted transfers (default: true)
159 std::string temp_directory; // Temporary directory for incomplete files
160
162 : chunk_size(65536), // 64KB chunks
164 max_retries(3),
165 timeout_seconds(30),
166 verify_checksums(true),
167 allow_resume(true),
168 temp_directory("./temp_transfers") {}
169};
170
174using FileTransferProgressCallback = std::function<void(const FileTransferProgress&)>;
175using FileTransferCompletedCallback = std::function<void(const std::string& transfer_id, bool success, const std::string& error_message)>;
176using FileTransferRequestCallback = std::function<bool(const std::string& peer_id, const FileMetadata& metadata, const std::string& transfer_id)>;
177using DirectoryTransferProgressCallback = std::function<void(const std::string& transfer_id, const std::string& current_file, uint64_t files_completed, uint64_t total_files, uint64_t bytes_completed, uint64_t total_bytes)>;
178using FileRequestCallback = std::function<bool(const std::string& peer_id, const std::string& file_path, const std::string& transfer_id)>;
179using DirectoryRequestCallback = std::function<bool(const std::string& peer_id, const std::string& directory_path, bool recursive, const std::string& transfer_id)>;
180
186public:
193
198
199 // Configuration
204 void set_config(const FileTransferConfig& config);
205
211
218 bool handle_binary_data(const std::string& peer_id, const std::vector<uint8_t>& binary_data);
219
220 // Callback registration
226
232
238
244
250
256
257 // File transfer operations
265 std::string send_file(const std::string& peer_id, const std::string& file_path,
266 const std::string& remote_filename = "");
267
275 std::string send_file_with_metadata(const std::string& peer_id, const std::string& file_path,
276 const FileMetadata& metadata);
277
286 std::string send_directory(const std::string& peer_id, const std::string& directory_path,
287 const std::string& remote_directory_name = "", bool recursive = true);
288
296 std::string request_file(const std::string& peer_id, const std::string& remote_file_path,
297 const std::string& local_path);
298
307 std::string request_directory(const std::string& peer_id, const std::string& remote_directory_path,
308 const std::string& local_directory_path, bool recursive = true);
309
316 bool accept_file_transfer(const std::string& transfer_id, const std::string& local_path);
317
324 bool reject_file_transfer(const std::string& transfer_id, const std::string& reason = "");
325
332 bool accept_directory_transfer(const std::string& transfer_id, const std::string& local_path);
333
340 bool reject_directory_transfer(const std::string& transfer_id, const std::string& reason = "");
341
342 // Transfer control
348 bool pause_transfer(const std::string& transfer_id);
349
355 bool resume_transfer(const std::string& transfer_id);
356
362 bool cancel_transfer(const std::string& transfer_id);
363
369 bool retry_transfer(const std::string& transfer_id);
370
371 // Information and monitoring
377 std::shared_ptr<FileTransferProgress> get_transfer_progress(const std::string& transfer_id) const;
378
383 std::vector<std::shared_ptr<FileTransferProgress>> get_active_transfers() const;
384
390 std::vector<std::shared_ptr<FileTransferProgress>> get_transfer_history(size_t limit = 0) const;
391
396
401 nlohmann::json get_transfer_statistics() const;
402
403 // Utility functions
410 static std::string calculate_file_checksum(const std::string& file_path, const std::string& algorithm = "sha256");
411
417 static FileMetadata get_file_metadata(const std::string& file_path);
418
425 static DirectoryMetadata get_directory_metadata(const std::string& directory_path, bool recursive = true);
426
433 static bool validate_file_path(const std::string& file_path, bool check_write = false);
434
435private:
436 RatsClient& client_;
437 FileTransferConfig config_;
438
439 // Transfer tracking
440 mutable std::mutex transfers_mutex_;
441 std::unordered_map<std::string, std::shared_ptr<FileTransferProgress>> active_transfers_;
442 std::unordered_map<std::string, std::shared_ptr<FileTransferProgress>> completed_transfers_;
443
444 // Pending transfers (not yet accepted/rejected)
445 mutable std::mutex pending_mutex_;
446 struct PendingFileTransfer {
447 FileMetadata metadata;
448 std::string peer_id;
449 };
450 struct PendingDirectoryTransfer {
451 DirectoryMetadata metadata;
452 std::string peer_id;
453 };
454 std::unordered_map<std::string, PendingFileTransfer> pending_transfers_;
455 std::unordered_map<std::string, PendingDirectoryTransfer> pending_directory_transfers_;
456
457 // Active directory transfers
458 mutable std::mutex directory_transfers_mutex_;
459 std::unordered_map<std::string, DirectoryMetadata> active_directory_transfers_;
460
461 // Chunk management
462 mutable std::mutex chunks_mutex_;
463 std::unordered_map<std::string, std::queue<FileChunk>> outgoing_chunks_;
464 std::unordered_map<std::string, std::unordered_map<uint64_t, FileChunk>> received_chunks_;
465
466 // Active chunk transfers waiting for binary data
467 struct PendingChunk {
468 std::string transfer_id;
469 uint64_t chunk_index;
470 uint64_t total_chunks;
471 uint64_t chunk_size;
472 uint64_t file_offset;
473 std::string checksum;
474 std::chrono::steady_clock::time_point created_at;
475 };
476 std::unordered_map<std::string, PendingChunk> pending_chunks_; // key: peer_id
477
478 // Worker threads
479 std::vector<std::thread> worker_threads_;
480 std::atomic<bool> running_;
481 std::condition_variable work_condition_;
482 std::mutex work_mutex_;
483 std::queue<std::string> work_queue_; // Transfer IDs that need processing
484
485 // Cleanup thread synchronization
486 std::condition_variable cleanup_condition_;
487 std::mutex cleanup_mutex_;
488
489 // Throttling synchronization
490 std::condition_variable throttle_condition_;
491 std::mutex throttle_mutex_;
492
493 // Callbacks
494 FileTransferProgressCallback progress_callback_;
495 FileTransferCompletedCallback completion_callback_;
496 FileTransferRequestCallback request_callback_;
497 DirectoryTransferProgressCallback directory_progress_callback_;
498 FileRequestCallback file_request_callback_;
499 DirectoryRequestCallback directory_request_callback_;
500
501 // Statistics
502 mutable std::mutex stats_mutex_;
503 uint64_t total_bytes_sent_;
504 uint64_t total_bytes_received_;
505 uint64_t total_files_sent_;
506 uint64_t total_files_received_;
507 std::chrono::steady_clock::time_point start_time_;
508
509 // Private methods
510 void initialize();
511 void shutdown();
512 void worker_thread_loop();
513 void cleanup_thread_loop();
514 void process_transfer(const std::string& transfer_id);
515
516 // Transfer management
517 std::string generate_transfer_id() const;
518 void start_file_send(const std::string& transfer_id);
519 void start_file_receive(const std::string& transfer_id);
520 void start_directory_send(const std::string& transfer_id);
521 void start_directory_receive(const std::string& transfer_id);
522 void handle_chunk_received(const FileChunk& chunk);
523 void handle_chunk_ack(const std::string& transfer_id, uint64_t chunk_index, bool success);
524
525 // File operations
526 bool create_temp_file(const std::string& transfer_id, uint64_t file_size);
527 bool finalize_received_file(const std::string& transfer_id, const std::string& final_path);
528
529 // Checksum validation
530 bool verify_chunk_checksum(const FileChunk& chunk);
531 std::string calculate_chunk_checksum(const std::vector<uint8_t>& data);
532
533 // Network message handling
534 void handle_transfer_request(const std::string& peer_id, const nlohmann::json& message);
535 void handle_transfer_response(const std::string& peer_id, const nlohmann::json& message);
536 void handle_chunk_metadata_message(const std::string& peer_id, const nlohmann::json& message);
537 void handle_chunk_binary_message(const std::string& peer_id, const std::vector<uint8_t>& binary_data);
538 void handle_chunk_ack_message(const std::string& peer_id, const nlohmann::json& message);
539 void handle_transfer_control(const std::string& peer_id, const nlohmann::json& message);
540 void handle_file_request(const std::string& peer_id, const nlohmann::json& message);
541 void handle_directory_request(const std::string& peer_id, const nlohmann::json& message);
542
543 // Message creation
544 nlohmann::json create_transfer_request_message(const FileMetadata& metadata, const std::string& transfer_id);
545 nlohmann::json create_transfer_response_message(const std::string& transfer_id, bool accepted, const std::string& reason = "");
546 std::vector<uint8_t> create_chunk_binary_message(const FileChunk& chunk);
547 nlohmann::json create_chunk_metadata_message(const FileChunk& chunk);
548 nlohmann::json create_chunk_ack_message(const std::string& transfer_id, uint64_t chunk_index, bool success, const std::string& error = "");
549 nlohmann::json create_control_message(const std::string& transfer_id, const std::string& action, const nlohmann::json& data = nlohmann::json::object());
550
551 // Progress tracking
552 void update_transfer_progress(const std::string& transfer_id, uint64_t bytes_delta = 0);
553 void complete_transfer(const std::string& transfer_id, bool success, const std::string& error_message = "");
554 void move_to_completed(const std::string& transfer_id);
555
556 // File system utilities
557 static bool ensure_directory_exists(const std::string& directory_path);
558 static std::string get_temp_file_path(const std::string& transfer_id, const std::string& temp_dir);
559 static std::string extract_filename(const std::string& file_path);
560 static std::string get_mime_type(const std::string& file_path);
561
562 // Binary chunk transmission helper
563 bool parse_chunk_binary_header(const std::vector<uint8_t>& binary_data, FileChunk& chunk);
564};
565
566} // namespace librats
567
File transfer manager class Handles efficient chunked file transfers with resume capability.
bool accept_directory_transfer(const std::string &transfer_id, const std::string &local_path)
Accept an incoming directory transfer.
std::vector< std::shared_ptr< FileTransferProgress > > get_active_transfers() const
Get all active transfers.
void set_directory_progress_callback(DirectoryTransferProgressCallback callback)
Set directory transfer progress callback.
nlohmann::json get_transfer_statistics() const
Get statistics about transfers.
void set_completion_callback(FileTransferCompletedCallback callback)
Set completion callback for transfer completion.
std::vector< std::shared_ptr< FileTransferProgress > > get_transfer_history(size_t limit=0) const
Get transfer history.
bool reject_directory_transfer(const std::string &transfer_id, const std::string &reason="")
Reject an incoming directory transfer.
bool accept_file_transfer(const std::string &transfer_id, const std::string &local_path)
Accept an incoming file transfer.
const FileTransferConfig & get_config() const
Get current configuration.
FileTransferManager(RatsClient &client, const FileTransferConfig &config=FileTransferConfig())
Constructor.
std::string send_file_with_metadata(const std::string &peer_id, const std::string &file_path, const FileMetadata &metadata)
Send a file with custom metadata.
void set_request_callback(FileTransferRequestCallback callback)
Set incoming transfer request callback.
void set_config(const FileTransferConfig &config)
Update transfer configuration.
void set_progress_callback(FileTransferProgressCallback callback)
Set progress callback for transfer updates.
std::shared_ptr< FileTransferProgress > get_transfer_progress(const std::string &transfer_id) const
Get progress information for a transfer.
static std::string calculate_file_checksum(const std::string &file_path, const std::string &algorithm="sha256")
Calculate file checksum.
void set_directory_request_callback(DirectoryRequestCallback callback)
Set directory request callback (called when receiving directory requests)
bool reject_file_transfer(const std::string &transfer_id, const std::string &reason="")
Reject an incoming file transfer.
void set_file_request_callback(FileRequestCallback callback)
Set file request callback (called when receiving file requests)
std::string send_directory(const std::string &peer_id, const std::string &directory_path, const std::string &remote_directory_name="", bool recursive=true)
Send an entire directory to a peer.
void clear_transfer_history()
Clear transfer history.
std::string request_directory(const std::string &peer_id, const std::string &remote_directory_path, const std::string &local_directory_path, bool recursive=true)
Request a directory from a remote peer.
bool pause_transfer(const std::string &transfer_id)
Pause an active transfer.
bool handle_binary_data(const std::string &peer_id, const std::vector< uint8_t > &binary_data)
Handle binary data that might be file transfer chunks.
bool resume_transfer(const std::string &transfer_id)
Resume a paused transfer.
bool cancel_transfer(const std::string &transfer_id)
Cancel an active or paused transfer.
bool retry_transfer(const std::string &transfer_id)
Retry a failed transfer.
static DirectoryMetadata get_directory_metadata(const std::string &directory_path, bool recursive=true)
Get directory metadata.
static FileMetadata get_file_metadata(const std::string &file_path)
Get file metadata.
std::string send_file(const std::string &peer_id, const std::string &file_path, const std::string &remote_filename="")
Send a file to a peer.
static bool validate_file_path(const std::string &file_path, bool check_write=false)
Validate file path and permissions.
std::string request_file(const std::string &peer_id, const std::string &remote_file_path, const std::string &local_path)
Request a file from a remote peer.
RatsClient - Core peer-to-peer networking client.
Definition librats.h:208
FileTransferStatus
File transfer status codes.
FileTransferDirection
File transfer direction.
std::function< void(const std::string &transfer_id, bool success, const std::string &error_message)> FileTransferCompletedCallback
std::function< bool(const std::string &peer_id, const std::string &file_path, const std::string &transfer_id)> FileRequestCallback
std::function< bool(const std::string &peer_id, const std::string &directory_path, bool recursive, const std::string &transfer_id)> DirectoryRequestCallback
std::function< void(const FileTransferProgress &)> FileTransferProgressCallback
Callback function types for file transfer events.
std::function< void(const std::string &transfer_id, const std::string &current_file, uint64_t files_completed, uint64_t total_files, uint64_t bytes_completed, uint64_t total_bytes)> DirectoryTransferProgressCallback
std::function< bool(const std::string &peer_id, const FileMetadata &metadata, const std::string &transfer_id)> FileTransferRequestCallback
Directory transfer metadata.
std::vector< FileMetadata > files
std::vector< DirectoryMetadata > subdirectories
size_t get_total_file_count() const
uint64_t get_total_size() const
File transfer chunk information.
std::vector< uint8_t > data
std::string transfer_id
std::string checksum
File metadata for transfers.
std::string relative_path
File transfer configuration.
File transfer progress information.
std::chrono::milliseconds get_elapsed_time() const
std::chrono::milliseconds estimated_time_remaining
std::chrono::steady_clock::time_point start_time
void update_transfer_rates(uint64_t new_bytes_transferred)
std::chrono::steady_clock::time_point last_update
FileTransferDirection direction
double get_completion_percentage() const