#pragma once #include #include #include #include #include namespace nxst { class TransferService { public: int startSend(size_t title_index, AccountUid uid); void cancelSend(); bool isSendDone() const { return sender_state.done.load(); } bool isSendCancelled() const { return sender_state.cancelled.load(); } bool isSendConnectionFailed() const { return sender_state.connection_failed.load(); } bool isSendProgressKnown() const { return sender_state.bytes_total.load() > 0; } bool isSendWorkersIdle() const { return !sender_active.load(); } double sendProgress() const { return sender_state.progress(); } std::string sendStatusText() const { return sender_state.getStatus(); } std::string sendFailReason() const { return sender_state.fail_reason; } int startReceive(size_t title_index, AccountUid uid, std::string title_name); void cancelReceive(); bool isReceiveDone() const { return receiver_state.done.load(); } bool isReceiveCancelled() const { return receiver_state.cancelled.load(); } bool isReceiveWorkersIdle() const { return !receiver_accept_active.load() && !receiver_broadcast_active.load(); } double receiveProgress() const { return receiver_state.progress(); } std::string receiveStatusText() const { return receiver_state.getStatus(); } bool restoreSucceeded() const { return restore_ok; } std::string restoreError() const { return restore_error; } private: // Sender TransferState sender_state; std::atomic sender_udp_sock{-1}; std::atomic sender_tcp_sock{-1}; std::atomic sender_active{false}; // Receiver TransferState receiver_state; std::atomic receiver_client_sock{-1}; std::atomic receiver_listen_sock{-1}; std::atomic receiver_bcast_sock{-1}; std::atomic receiver_accept_active{false}; std::atomic receiver_broadcast_active{false}; pthread_t receiver_bcast_thread{}; // Stored at startReceive, read after network transfer completes size_t restore_title_index{0}; AccountUid restore_uid{}; std::string restore_title_name; bool restore_ok{false}; std::string restore_error; // Sender thread struct SenderArgs { TransferService* svc; size_t title_index; AccountUid uid; }; static void* senderEntry(void* arg); void runSender(size_t title_index, AccountUid uid); void failSend(const std::string& reason); int findServer(char* out_ip); // Receiver threads struct AcceptArgs { TransferService* svc; int server_fd; }; static void* broadcastEntry(void* arg); static void* acceptEntry(void* arg); void runBroadcast(); void runAccept(int server_fd); std::string replaceUsername(const std::string& file_path) const; }; } // namespace nxst