WdtTransferRequest.h (97 lines of code) (raw):

/** * Copyright (c) 2014-present, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the * LICENSE file in the root directory of this source tree. */ #pragma once #include <wdt/ErrorCodes.h> #include <wdt/Protocol.h> #include <wdt/WdtOptions.h> #include <folly/Optional.h> #include <functional> #include <map> #include <memory> #include <string> #include <vector> namespace facebook { namespace wdt { /** * Users of wdt apis can provide a list of info * for files. A info represents a file name with * information such as size, and flags * to read the file with */ struct WdtFileInfo { /** * Name of the file to be read, generally as relative path */ std::string fileName; /// Size of the file to be read, default is -1 int64_t fileSize; /// File descriptor. If this is not -1, then wdt uses this to read int fd{-1}; /// Whether read should be done using o_direct. If fd is set, this flag will /// be set automatically to match the fd open mode bool directReads{false}; /// Constructor for file info with name, size and odirect request WdtFileInfo(const std::string& name, int64_t size, bool directReads); /** * Constructor with name, size and fd * If this constructor is used, then whether to do direct reads is decided * by fd flags. * Attempt to disambiguate the 2 constructors by having the fd first * and string last in this one. */ WdtFileInfo(int fd, int64_t size, const std::string& name); /// Verify that we can align for reading in O_DIRECT and /// the flags make sense void verifyAndFixFlags(); }; /** * Basic Uri class to parse and get information from wdt url * This class can be used in two ways : * 1. Construct the class with a url and get fields like * hostname, and different get parameters * 2. Construct an empty object and set the fields, and * generate a url * * Example of a url : * wdt://localhost?dir=/tmp/wdt&ports=22356,22357 */ class WdtUri { public: /// Empty Uri object WdtUri() = default; /// Construct the uri object using a string url explicit WdtUri(const std::string& url); /// Get the host name of the url std::string getHostName() const; /// Get the port number int32_t getPort() const; /// Get the query param by key std::string getQueryParam(const std::string& key) const; /// Get all the query params const std::map<std::string, std::string>& getQueryParams() const; /// Sets hostname to generate a url void setHostName(const std::string& hostName); /// Set the port for the uri void setPort(int32_t port); /// Sets a query param in the query params map void setQueryParam(const std::string& key, const std::string& value); /// Generate url by serializing the members of this struct std::string generateUrl() const; /// Url escape a value (which can be binary) static std::string escape(const std::string& binaryStr); /// Url unescape a value (escaped by escape()) - returns true if successful, /// false if there is a malformed % sequence in the string static bool unescape(std::string& result, folly::StringPiece escapedValue); /// 0-16 -> '0'-'f' static char toHex(unsigned char v); /// '0'-'f' -> 0-16 static int fromHex(char c); /// Assignment operator to convert string to wdt uri object WdtUri& operator=(const std::string& url); /// Clears the field of the uri void clear(); /// Get the error code if any during parsing ErrorCode getErrorCode() const; private: /** * Returns whether the url could be processed successfully. Populates * the values on a best effort basis. */ ErrorCode process(const std::string& url); // TODO: use a vector instead, we don't really need to search... /** * Map of get parameters of the url. Key and value * of the map are the name and value of get parameter respectively */ std::map<std::string, std::string> queryParams_; /// Prefix of the wdt url const std::string WDT_URL_PREFIX{"wdt://"}; /// Hostname/ip address in the uri std::string hostName_{""}; /// Port of the uri int32_t port_{-1}; /// Error code that reflects that status of parsing url ErrorCode errorCode_{OK}; }; /** * Basic request for creating wdt objects * This request can be used for creating receivers and the * counter part sender or vice versa */ struct WdtTransferRequest { /** * Transfer Id for the transfer. It has to be same * on both sender and receiver */ std::string transferId; /// Encryption protocol:sessionKey / secret (not printed), empty = clear text EncryptionParams encryptionData; /// Protocol version on sender and receiver int64_t protocolVersion{Protocol::protocol_version}; /// Ports on which receiver is listening / sender is sending to std::vector<int32_t> ports; /// Address on which receiver binded the ports / sender is sending data to std::string hostName; /// Unique identifier for destination. This is useful to distinguish multiple /// destinations in the same host std::string destIdentifier; /// Namespace for the transfer std::string wdtNamespace; /// Directory to write the data to / read the data from std::string directory; /// Only used for the sender and when not using directory discovery std::vector<WdtFileInfo> fileInfo; /// Only used for the sender and when not using directory discovery. /// Sender repeatedly invokes this function to get list of files to /// send and stops when the function return folly::none. File transfer /// is done in batches. After intiating the transfer for a initial list of /// files (either via fileInfo or a call to fileInfoGenerator), we wait /// until transfer is complete before we read the next batch, if any, by /// invoking fileInfoGenerator again. using FileInfoGenerator = std::function<folly::Optional<std::vector<WdtFileInfo>>()>; FileInfoGenerator fileInfoGenerator{}; /// Use fileInfo even if empty (don't use the directory exploring) bool disableDirectoryTraversal{false}; // download resumption is enabled on the receiver side // and is requested from the sender bool downloadResumptionEnabled{false}; /// TLS is enabled on the receiver side bool tls{false}; /// Number of GBytes after iv is changed int64_t ivChangeInterval{0}; /// Any error associated with this transfer request upon processing ErrorCode errorCode{OK}; /// Empty constructor WdtTransferRequest() { } /** * Constructor with start port and num ports. Fills the vector with * ports from [startPort, startPort + numPorts) */ WdtTransferRequest(int startPort, int numPorts, const std::string& directory); /// Constructor to construct the request object from a url string explicit WdtTransferRequest(const std::string& uriString); /// @return generates wdt connection url and has encryption secret. /// Returned secret should not be logged std::string genWdtUrlWithSecret() const; /// @return returns a string describing this request. This string can be /// logged std::string getLogSafeString() const; /// Serialize the ports into uri void serializePorts(WdtUri& wdtUri) const; /// Get stringified port list std::string getSerializedPortsList() const; /// Operator for finding if two request objects are equal bool operator==(const WdtTransferRequest& that) const; /// Overloaded operator for printing request info friend std::ostream& operator<<(std::ostream& os, const WdtTransferRequest& req); const static int LEGACY_PROTCOL_VERSION; /// Names of the get parameters for different fields const static std::string TRANSFER_ID_PARAM; /** Constant for for the protocol version get parameter in uri */ const static std::string RECEIVER_PROTOCOL_VERSION_PARAM; const static std::string DIRECTORY_PARAM; const static std::string PORTS_PARAM; const static std::string START_PORT_PARAM; const static std::string NUM_PORTS_PARAM; /// Encryption parameters (proto:key for now, certificate,... potentially) const static std::string ENCRYPTION_PARAM; const static std::string TLS_PARAM; const static std::string NAMESPACE_PARAM; const static std::string DEST_IDENTIFIER_PARAM; const static std::string DOWNLOAD_RESUMPTION_PARAM; const static std::string IV_CHANGE_INTERVAL_PARAM; /// Get ports vector from startPort and numPorts static std::vector<int32_t> genPortsVector(int32_t startPort, int32_t numPorts); private: /** * Serialize this structure into a url string containing all fields * Will only put the real encoded secret if forLogging is set to false */ std::string generateUrlInternal(bool genFull, bool forLogging) const; }; } }