Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add body to network errors #14

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 6 additions & 5 deletions src/libstore/daemon.cc
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ struct TunnelLogger : public Logger
}
};

struct TunnelSink : Sink
struct TunnelSink : public Sink
{
Sink & to;
TunnelSink(Sink & to) : to(to) { }
Expand Down Expand Up @@ -175,7 +175,7 @@ struct TunnelSource : BufferedSource

/* If the NAR archive contains a single file at top-level, then save
the contents of the file to `s'. Otherwise barf. */
struct RetrieveRegularNARSink : ParseSink
struct RetrieveRegularNARSink : public ParseSink
{
bool regular;
string s;
Expand Down Expand Up @@ -721,9 +721,10 @@ static void performOp(TunnelLogger * logger, ref<Store> store,
if (GET_PROTOCOL_MINOR(clientVersion) >= 21)
source = std::make_unique<TunnelSource>(from, to);
else {
TeeSink tee(from);
parseDump(tee, tee.source);
saved = std::move(*tee.source.data);
TeeSource tee(from);
ParseSink sink;
parseDump(sink, tee);
saved = std::move(*tee.data);
source = std::make_unique<StringSource>(saved);
}

Expand Down
13 changes: 7 additions & 6 deletions src/libstore/export-import.cc
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

namespace nix {

struct HashAndWriteSink : Sink
struct HashAndWriteSink : public Sink
{
Sink & writeSink;
HashSink hashSink;
Expand Down Expand Up @@ -77,8 +77,9 @@ StorePaths Store::importPaths(Source & source, std::shared_ptr<FSAccessor> acces
if (n != 1) throw Error("input doesn't look like something created by 'nix-store --export'");

/* Extract the NAR from the source. */
TeeSink tee(source);
parseDump(tee, tee.source);
TeeSource tee(source);
ParseSink sink;
parseDump(sink, tee);

uint32_t magic = readInt(source);
if (magic != exportMagic)
Expand All @@ -94,15 +95,15 @@ StorePaths Store::importPaths(Source & source, std::shared_ptr<FSAccessor> acces
if (deriver != "")
info.deriver = parseStorePath(deriver);

info.narHash = hashString(htSHA256, *tee.source.data);
info.narSize = tee.source.data->size();
info.narHash = hashString(htSHA256, *tee.data);
info.narSize = tee.data->size();

// Ignore optional legacy signature.
if (readInt(source) == 1)
readString(source);

// Can't use underlying source, which would have been exhausted
auto source = StringSource { *tee.source.data };
auto source = StringSource { *tee.data };
addToStore(info, source, NoRepair, checkSigs, accessor);

res.push_back(info.path);
Expand Down
40 changes: 28 additions & 12 deletions src/libstore/filetransfer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include <queue>
#include <random>
#include <thread>
#include <variant>

using namespace std::string_literals;

Expand Down Expand Up @@ -56,7 +57,6 @@ struct curlFileTransfer : public FileTransfer
Callback<FileTransferResult> callback;
CURL * req = 0;
bool active = false; // whether the handle has been added to the multi object
std::string status;

unsigned int attempt = 0;

Expand All @@ -72,6 +72,8 @@ struct curlFileTransfer : public FileTransfer

curl_off_t writtenToSink = 0;

inline static const std::set<long> successfulStatuses;

/* Get the HTTP status code, or 0 for other protocols. */
long getHTTPStatus()
{
Expand All @@ -98,7 +100,7 @@ struct curlFileTransfer : public FileTransfer

/* Only write data to the sink if this is a
successful response. */
if (httpStatus == 0 || httpStatus == 200 || httpStatus == 201 || httpStatus == 206) {
if (successfulStatuses.find(httpStatus) != successfulStatuses.end()) {
writtenToSink += len;
this->request.dataCallback((char *) data, len);
}
Expand All @@ -122,7 +124,7 @@ struct curlFileTransfer : public FileTransfer
if (requestHeaders) curl_slist_free_all(requestHeaders);
try {
if (!done)
fail(FileTransferError(Interrupted, "download of '%s' was interrupted", request.uri));
fail(FileTransferError(Interrupted, nullptr, "download of '%s' was interrupted", request.uri));
} catch (...) {
ignoreException();
}
Expand All @@ -142,7 +144,9 @@ struct curlFileTransfer : public FileTransfer
}

LambdaSink finalSink;
std::shared_ptr<CompressionSink> decompressionSink;
// std::shared_ptr< std::variant<Sink, CompressionSink> > decompressionSink;
// std::variant< std::shared_ptr<Sink>, std::shared_ptr<CompressionSink> > decompressionSink;
std::shared_ptr<Sink> decompressionSink;

std::exception_ptr writeException;

Expand All @@ -152,8 +156,13 @@ struct curlFileTransfer : public FileTransfer
size_t realSize = size * nmemb;
result.bodySize += realSize;

if (!decompressionSink)
decompressionSink = makeDecompressionSink(encoding, finalSink);
// if (!decompressionSink)
// // decompressionSink = makeDecompressionSink(encoding, finalSink);
// decompressionSink.reset(*makeDecompressionSink(encoding, finalSink));

// Let's see some types:
// makeDecompressionSink(...) :: ref<CompressionSink>
//

(*decompressionSink)((unsigned char *) contents, realSize);

Expand All @@ -174,6 +183,7 @@ struct curlFileTransfer : public FileTransfer
size_t realSize = size * nmemb;
std::string line((char *) contents, realSize);
printMsg(lvlVomit, format("got header for '%s': %s") % request.uri % trim(line));
std::string status;
if (line.compare(0, 5, "HTTP/") == 0) { // new response starts
result.etag = "";
auto ss = tokenizeString<vector<string>>(line, " ");
Expand All @@ -182,6 +192,13 @@ struct curlFileTransfer : public FileTransfer
result.bodySize = 0;
acceptRanges = false;
encoding = "";
if (successfulStatuses.find(std::stoi(status)) != successfulStatuses.end()) {
// Here we want to construct just the sink
decompressionSink.reset(static_cast<Sink>(makeDecompressionSink(encoding, finalSink).get_ptr()));
} else {
// In this case we want to construct a TeeSink, to keep the error around
decompressionSink = std::make_shared<TeeSink>{*decompressionSink};
}
} else {
auto i = line.find(':');
if (i != string::npos) {
Expand Down Expand Up @@ -352,8 +369,7 @@ struct curlFileTransfer : public FileTransfer
if (writeException)
failEx(writeException);

else if (code == CURLE_OK &&
(httpStatus == 200 || httpStatus == 201 || httpStatus == 204 || httpStatus == 206 || httpStatus == 304 || httpStatus == 0 /* other protocol */))
else if (code == CURLE_OK && successfulStatuses.find(httpStatus) != successfulStatuses.end())
{
result.cached = httpStatus == 304;
act.progress(result.bodySize, result.bodySize);
Expand Down Expand Up @@ -410,14 +426,14 @@ struct curlFileTransfer : public FileTransfer

auto exc =
code == CURLE_ABORTED_BY_CALLBACK && _isInterrupted
? FileTransferError(Interrupted, fmt("%s of '%s' was interrupted", request.verb(), request.uri))
? FileTransferError(Interrupted, nullptr, fmt("%s of '%s' was interrupted", request.verb(), request.uri))
: httpStatus != 0
? FileTransferError(err,
? FileTransferError(err, nullptr,
fmt("unable to %s '%s': HTTP error %d",
request.verb(), request.uri, httpStatus)
+ (code == CURLE_OK ? "" : fmt(" (curl error: %s)", curl_easy_strerror(code)))
)
: FileTransferError(err,
: FileTransferError(err, nullptr,
fmt("unable to %s '%s': %s (%d)",
request.verb(), request.uri, curl_easy_strerror(code), code));

Expand Down Expand Up @@ -675,7 +691,7 @@ struct curlFileTransfer : public FileTransfer
auto s3Res = s3Helper.getObject(bucketName, key);
FileTransferResult res;
if (!s3Res.data)
throw FileTransferError(NotFound, fmt("S3 object '%s' does not exist", request.uri));
throw FileTransferError(NotFound, nullptr, fmt("S3 object '%s' does not exist", request.uri));
res.data = s3Res.data;
callback(std::move(res));
#else
Expand Down
5 changes: 3 additions & 2 deletions src/libstore/filetransfer.hh
Original file line number Diff line number Diff line change
Expand Up @@ -103,9 +103,10 @@ class FileTransferError : public Error
{
public:
FileTransfer::Error error;
std::optional<string> response;
template<typename... Args>
FileTransferError(FileTransfer::Error error, const Args & ... args)
: Error(args...), error(error)
FileTransferError(FileTransfer::Error error, std::optional<string> response, const Args & ... args)
: Error(args...), error(error), response(response)
{ }
};

Expand Down
2 changes: 1 addition & 1 deletion src/libstore/references.cc
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ static void search(const unsigned char * s, size_t len,
}


struct RefScanSink : Sink
struct RefScanSink : public Sink
{
HashSink hashSink;
StringSet hashes;
Expand Down
2 changes: 1 addition & 1 deletion src/libutil/archive.cc
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,7 @@ void parseDump(ParseSink & sink, Source & source)
}


struct RestoreSink : ParseSink
struct RestoreSink : public ParseSink
{
Path dstPath;
AutoCloseFD fd;
Expand Down
7 changes: 0 additions & 7 deletions src/libutil/archive.hh
Original file line number Diff line number Diff line change
Expand Up @@ -63,13 +63,6 @@ struct ParseSink
virtual void createSymlink(const Path & path, const string & target) { };
};

struct TeeSink : ParseSink
{
TeeSource source;

TeeSink(Source & source) : source(source) { }
};

void parseDump(ParseSink & sink, Source & source);

void restorePath(const Path & path, Source & source);
Expand Down
18 changes: 9 additions & 9 deletions src/libutil/compression.cc
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
namespace nix {

// Don't feed brotli too much at once.
struct ChunkedCompressionSink : CompressionSink
struct ChunkedCompressionSink : public CompressionSink
{
uint8_t outbuf[32 * 1024];

Expand All @@ -36,15 +36,15 @@ struct ChunkedCompressionSink : CompressionSink
virtual void writeInternal(const unsigned char * data, size_t len) = 0;
};

struct NoneSink : CompressionSink
struct NoneSink : public CompressionSink
{
Sink & nextSink;
NoneSink(Sink & nextSink) : nextSink(nextSink) { }
void finish() override { flush(); }
void write(const unsigned char * data, size_t len) override { nextSink(data, len); }
};

struct GzipDecompressionSink : CompressionSink
struct GzipDecompressionSink : public CompressionSink
{
Sink & nextSink;
z_stream strm;
Expand Down Expand Up @@ -104,7 +104,7 @@ struct GzipDecompressionSink : CompressionSink
}
};

struct XzDecompressionSink : CompressionSink
struct XzDecompressionSink : public CompressionSink
{
Sink & nextSink;
uint8_t outbuf[BUFSIZ];
Expand Down Expand Up @@ -156,7 +156,7 @@ struct XzDecompressionSink : CompressionSink
}
};

struct BzipDecompressionSink : ChunkedCompressionSink
struct BzipDecompressionSink : public ChunkedCompressionSink
{
Sink & nextSink;
bz_stream strm;
Expand Down Expand Up @@ -209,7 +209,7 @@ struct BzipDecompressionSink : ChunkedCompressionSink
}
};

struct BrotliDecompressionSink : ChunkedCompressionSink
struct BrotliDecompressionSink : public ChunkedCompressionSink
{
Sink & nextSink;
BrotliDecoderState * state;
Expand Down Expand Up @@ -285,7 +285,7 @@ ref<CompressionSink> makeDecompressionSink(const std::string & method, Sink & ne
throw UnknownCompressionMethod("unknown compression method '%s'", method);
}

struct XzCompressionSink : CompressionSink
struct XzCompressionSink : public CompressionSink
{
Sink & nextSink;
uint8_t outbuf[BUFSIZ];
Expand Down Expand Up @@ -364,7 +364,7 @@ struct XzCompressionSink : CompressionSink
}
};

struct BzipCompressionSink : ChunkedCompressionSink
struct BzipCompressionSink : public ChunkedCompressionSink
{
Sink & nextSink;
bz_stream strm;
Expand Down Expand Up @@ -417,7 +417,7 @@ struct BzipCompressionSink : ChunkedCompressionSink
}
};

struct BrotliCompressionSink : ChunkedCompressionSink
struct BrotliCompressionSink : public ChunkedCompressionSink
{
Sink & nextSink;
uint8_t outbuf[BUFSIZ];
Expand Down
2 changes: 1 addition & 1 deletion src/libutil/compression.hh
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

namespace nix {

struct CompressionSink : BufferedSink
struct CompressionSink : public BufferedSink
{
virtual void finish() = 0;
};
Expand Down
2 changes: 1 addition & 1 deletion src/libutil/hash.hh
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ string printHashType(HashType ht);

union Ctx;

struct AbstractHashSink : virtual Sink
struct AbstractHashSink : public virtual Sink
{
virtual HashResult finish() = 0;
};
Expand Down
Loading