Skip to content
Snippets Groups Projects
Select Git revision
  • master default protected
  • release/202005
  • release/202001
  • release/201912
  • release/201911
  • release/releaseWindowsTestOne
  • release/windowsReleaseTest
  • release/releaseTest
  • release/releaseWindowsTest
  • release/201910
  • release/qt/201910
  • release/windows-test/201910
  • release/201908
  • release/201906
  • release/201905
  • release/201904
  • release/201903
  • release/201902
  • release/201901
  • release/201812
  • 4.0.0
  • 2.2.0
  • 2.1.0
  • 2.0.1
  • 2.0.0
  • 1.4.1
  • 1.4.0
  • 1.3.0
  • 1.2.0
  • 1.1.0
30 results

data_transfer.h

Blame
  • Code owners
    Assign users and groups as approvers for specific file changes. Learn more.
    data_transfer.h 6.70 KiB
    /*
     *  Copyright (C) 2004-2024 Savoir-faire Linux Inc.
     *
     *  Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com>
     *
     *  This program is free software; you can redistribute it and/or modify
     *  it under the terms of the GNU General Public License as published by
     *  the Free Software Foundation; either version 3 of the License, or
     *  (at your option) any later version.
     *
     *  This program is distributed in the hope that it will be useful,
     *  but WITHOUT ANY WARRANTY; without even the implied warranty of
     *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     *  GNU General Public License for more details.
     *
     *  You should have received a copy of the GNU General Public License
     *  along with this program; if not, write to the Free Software
     *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.
     */
    
    #pragma once
    
    #include "jami/datatransfer_interface.h"
    #include "noncopyable.h"
    
    #include <dhtnet/multiplexed_socket.h>
    
    #include <fstream>
    #include <functional>
    #include <memory>
    #include <optional>
    #include <string>
    
    namespace jami {
    
    libjami::DataTransferId generateUID(std::mt19937_64& engine);
    
    class Stream;
    
    struct IncomingFileInfo
    {
        libjami::DataTransferId id;
        std::shared_ptr<Stream> stream;
    };
    
    struct WaitingRequest
    {
        std::string fileId;
        std::string interactionId;
        std::string sha3sum;
        std::string path;
        std::size_t totalSize;
        MSGPACK_DEFINE(fileId, interactionId, sha3sum, path, totalSize)
    };
    
    typedef std::function<void(const std::string&)> InternalCompletionCb;
    typedef std::function<void()> OnFinishedCb;
    
    class FileInfo
    {
    public:
        FileInfo(const std::shared_ptr<dhtnet::ChannelSocket>& channel,
                 const std::string& fileId,
                 const std::string& interactionId,
                 const libjami::DataTransferInfo& info);
        virtual ~FileInfo() {}
        virtual void process() = 0;
        std::shared_ptr<dhtnet::ChannelSocket> channel() const { return channel_; }
        libjami::DataTransferInfo info() const { return info_; }
        virtual void cancel() = 0;
        void onFinished(std::function<void(uint32_t)>&& cb) { finishedCb_ = std::move(cb); }
        void emit(libjami::DataTransferEventCode code);
    
    protected:
        std::atomic_bool isUserCancelled_ {false};
        std::string fileId_ {};
        std::string interactionId_ {};
        libjami::DataTransferInfo info_ {};
        std::shared_ptr<dhtnet::ChannelSocket> channel_ {};
        std::function<void(uint32_t)> finishedCb_ {};
    };
    
    class IncomingFile : public FileInfo, public std::enable_shared_from_this<IncomingFile>
    {
    public:
        IncomingFile(const std::shared_ptr<dhtnet::ChannelSocket>& channel,
                     const libjami::DataTransferInfo& info,
                     const std::string& fileId,
                     const std::string& interactionId,
                     const std::string& sha3Sum = "");
        ~IncomingFile();
        void process() override;
        void cancel() override;
    
    private:
        std::weak_ptr<IncomingFile> weak()
        {
            return std::static_pointer_cast<IncomingFile>(shared_from_this());
        }
        std::mutex streamMtx_;
        std::ofstream stream_;
        std::string sha3Sum_ {};
    };
    
    class OutgoingFile : public FileInfo
    {
    public:
        OutgoingFile(const std::shared_ptr<dhtnet::ChannelSocket>& channel,
                     const std::string& fileId,
                     const std::string& interactionId,
                     const libjami::DataTransferInfo& info,
                     size_t start = 0,
                     size_t end = 0);
        ~OutgoingFile();
        void process() override;
        void cancel() override;
    
    private:
        std::ifstream stream_;
        size_t start_ {0};
        size_t end_ {0};
    };
    
    class TransferManager : public std::enable_shared_from_this<TransferManager>
    {
    public:
        TransferManager(const std::string& accountId, const std::string& accountUri, const std::string& to, const std::mt19937_64& rand);
        ~TransferManager();
    
        /**
         * Send a file to a channel
         * @param channel       channel to use
         * @param fileId        fileId of the transfer
         * @param interactionId interactionId of the transfer
         * @param path          path of the file
         * @param start         start offset
         * @param end           end
         */
        void transferFile(const std::shared_ptr<dhtnet::ChannelSocket>& channel,
                          const std::string& fileId,
                          const std::string& interactionId,
                          const std::string& path,
                          size_t start = 0,
                          size_t end = 0,
                          OnFinishedCb onFinished = {});
    
        /**
         * Refuse a transfer
         * @param id        of the transfer
         */
        bool cancel(const std::string& fileId);
    
        /**
         * Get current transfer info
         * @param id        of the transfer
         * @param total     size
         * @param path      path of the file
         * @param progress  current progress
         * @return if found
         */
        bool info(const std::string& fileId,
                  std::string& path,
                  int64_t& total,
                  int64_t& progress) const noexcept;
    
        /**
         * Inform the transfer manager that a transfer is waited (and will be automatically accepted)
         * @param id              of the transfer
         * @param interactionId   linked interaction
         * @param sha3sum         attended sha3sum
         * @param path            where the file will be downloaded
         * @param total           total size of the file
         */
        void waitForTransfer(const std::string& fileId,
                             const std::string& interactionId,
                             const std::string& sha3sum,
                             const std::string& path,
                             std::size_t total);
    
        /**
         * Handle incoming transfer
         * @param id        Related id
         * @param channel   Related channel
         */
        void onIncomingFileTransfer(const std::string& fileId,
                                    const std::shared_ptr<dhtnet::ChannelSocket>& channel);
    
        /**
         * Retrieve path of a file
         * @param id
         */
        std::filesystem::path path(const std::string& fileId) const;
    
        /**
         * Retrieve waiting files
         * @return waiting list
         */
        std::vector<WaitingRequest> waitingRequests() const;
        bool isWaiting(const std::string& fileId) const;
        void onIncomingProfile(const std::shared_ptr<dhtnet::ChannelSocket>& channel, const std::string& sha3Sum = "");
    
        /**
         * @param contactId     contact's id
         * @return where profile.vcf is stored
         */
        std::filesystem::path profilePath(const std::string& contactId) const;
    
    private:
        std::weak_ptr<TransferManager> weak()
        {
            return std::static_pointer_cast<TransferManager>(shared_from_this());
        }
        NON_COPYABLE(TransferManager);
        class Impl;
        std::unique_ptr<Impl> pimpl_;
    };
    
    } // namespace jami