eldritch horrors
c55dcc6c13
without this we will not be able to get rid of makeDecompressionSink,
which in turn will be necessary to get rid of sourceToSink (since the
libarchive archive wrapper *must* be a Source due to api limitations)
Change-Id: Iccd3d333ba2cbcab49cb5a1d3125624de16bce27
146 lines
4 KiB
C++
146 lines
4 KiB
C++
#pragma once
|
||
///@file
|
||
|
||
#include "box_ptr.hh"
|
||
#include "logging.hh"
|
||
#include "serialise.hh"
|
||
#include "types.hh"
|
||
#include "config.hh"
|
||
|
||
#include <string>
|
||
#include <future>
|
||
|
||
namespace nix {
|
||
|
||
struct FileTransferSettings : Config
|
||
{
|
||
Setting<bool> enableHttp2{this, true, "http2",
|
||
"Whether to enable HTTP/2 support."};
|
||
|
||
Setting<std::string> userAgentSuffix{this, "", "user-agent-suffix",
|
||
"String appended to the user agent in HTTP requests."};
|
||
|
||
Setting<size_t> httpConnections{
|
||
this, 25, "http-connections",
|
||
R"(
|
||
The maximum number of parallel TCP connections used to fetch
|
||
files from binary caches and by other downloads. It defaults
|
||
to 25. 0 means no limit.
|
||
)",
|
||
{"binary-caches-parallel-connections"}};
|
||
|
||
Setting<unsigned long> connectTimeout{
|
||
this, 0, "connect-timeout",
|
||
R"(
|
||
The timeout (in seconds) for establishing connections in the
|
||
binary cache substituter. It corresponds to `curl`’s
|
||
`--connect-timeout` option. A value of 0 means no limit.
|
||
)"};
|
||
|
||
Setting<unsigned long> stalledDownloadTimeout{
|
||
this, 300, "stalled-download-timeout",
|
||
R"(
|
||
The timeout (in seconds) for receiving data from servers
|
||
during download. Lix cancels idle downloads after this
|
||
timeout's duration.
|
||
)"};
|
||
|
||
Setting<unsigned int> tries{this, 5, "download-attempts",
|
||
"How often Lix will attempt to download a file before giving up."};
|
||
};
|
||
|
||
extern FileTransferSettings fileTransferSettings;
|
||
|
||
struct FileTransferRequest
|
||
{
|
||
std::string uri;
|
||
Headers headers;
|
||
std::string expectedETag;
|
||
bool verifyTLS = true;
|
||
bool head = false;
|
||
size_t tries = fileTransferSettings.tries;
|
||
unsigned int baseRetryTimeMs = 250;
|
||
ActivityId parentAct;
|
||
std::optional<std::string> data;
|
||
std::string mimeType;
|
||
|
||
FileTransferRequest(std::string_view uri)
|
||
: uri(uri), parentAct(getCurActivity()) { }
|
||
|
||
std::string verb()
|
||
{
|
||
return data ? "upload" : "download";
|
||
}
|
||
};
|
||
|
||
struct FileTransferResult
|
||
{
|
||
bool cached = false;
|
||
std::string etag;
|
||
std::string effectiveUri;
|
||
std::string data;
|
||
uint64_t bodySize = 0;
|
||
/* An "immutable" URL for this resource (i.e. one whose contents
|
||
will never change), as returned by the `Link: <url>;
|
||
rel="immutable"` header. */
|
||
std::optional<std::string> immutableUrl;
|
||
};
|
||
|
||
class Store;
|
||
|
||
struct FileTransfer
|
||
{
|
||
virtual ~FileTransfer() { }
|
||
|
||
/**
|
||
* Enqueue a data transfer request, returning a future to the result of
|
||
* the download. The future may throw a FileTransferError
|
||
* exception.
|
||
*/
|
||
virtual std::future<FileTransferResult> enqueueFileTransfer(const FileTransferRequest & request) = 0;
|
||
|
||
/**
|
||
* Synchronously transfer a file.
|
||
*/
|
||
FileTransferResult transfer(const FileTransferRequest & request);
|
||
|
||
/**
|
||
* Download a file, returning its contents through a source. Will not return
|
||
* before the transfer has fully started, ensuring that any errors thrown by
|
||
* the setup phase (e.g. HTTP 404 or similar errors) are not postponed to be
|
||
* thrown by the returned source. The source will only throw errors detected
|
||
* during the transfer itself (decompression errors, connection drops, etc).
|
||
*/
|
||
virtual box_ptr<Source> download(FileTransferRequest && request) = 0;
|
||
|
||
enum Error { NotFound, Forbidden, Misc, Transient, Interrupted };
|
||
};
|
||
|
||
/**
|
||
* @return a shared FileTransfer object.
|
||
*
|
||
* Using this object is preferred because it enables connection reuse
|
||
* and HTTP/2 multiplexing.
|
||
*/
|
||
ref<FileTransfer> getFileTransfer();
|
||
|
||
/**
|
||
* @return a new FileTransfer object
|
||
*
|
||
* Prefer getFileTransfer() to this; see its docs for why.
|
||
*/
|
||
ref<FileTransfer> makeFileTransfer();
|
||
|
||
class FileTransferError : public Error
|
||
{
|
||
public:
|
||
FileTransfer::Error error;
|
||
/// intentionally optional
|
||
std::optional<std::string> response;
|
||
|
||
template<typename... Args>
|
||
FileTransferError(FileTransfer::Error error, std::optional<std::string> response, const Args & ... args);
|
||
};
|
||
|
||
}
|