mirror of
https://github.com/hrydgard/ppsspp.git
synced 2024-11-30 08:50:33 +00:00
Merge pull request #11700 from unknownbrackets/http-error
http: Report errors reading discs
This commit is contained in:
commit
127330feec
@ -25,12 +25,12 @@
|
||||
|
||||
// Takes ownership of backend.
|
||||
CachingFileLoader::CachingFileLoader(FileLoader *backend)
|
||||
: backend_(backend) {
|
||||
: ProxiedFileLoader(backend) {
|
||||
}
|
||||
|
||||
void CachingFileLoader::Prepare() {
|
||||
std::call_once(preparedFlag_, [this](){
|
||||
filesize_ = backend_->FileSize();
|
||||
filesize_ = ProxiedFileLoader::FileSize();
|
||||
if (filesize_ > 0) {
|
||||
InitCache();
|
||||
}
|
||||
@ -41,27 +41,25 @@ CachingFileLoader::~CachingFileLoader() {
|
||||
if (filesize_ > 0) {
|
||||
ShutdownCache();
|
||||
}
|
||||
// Takes ownership.
|
||||
delete backend_;
|
||||
}
|
||||
|
||||
bool CachingFileLoader::Exists() {
|
||||
if (exists_ == -1) {
|
||||
exists_ = backend_->Exists() ? 1 : 0;
|
||||
exists_ = ProxiedFileLoader::Exists() ? 1 : 0;
|
||||
}
|
||||
return exists_ == 1;
|
||||
}
|
||||
|
||||
bool CachingFileLoader::ExistsFast() {
|
||||
if (exists_ == -1) {
|
||||
return backend_->ExistsFast();
|
||||
return ProxiedFileLoader::ExistsFast();
|
||||
}
|
||||
return exists_ == 1;
|
||||
}
|
||||
|
||||
bool CachingFileLoader::IsDirectory() {
|
||||
if (isDirectory_ == -1) {
|
||||
isDirectory_ = backend_->IsDirectory() ? 1 : 0;
|
||||
isDirectory_ = ProxiedFileLoader::IsDirectory() ? 1 : 0;
|
||||
}
|
||||
return isDirectory_ == 1;
|
||||
}
|
||||
@ -71,10 +69,6 @@ s64 CachingFileLoader::FileSize() {
|
||||
return filesize_;
|
||||
}
|
||||
|
||||
std::string CachingFileLoader::Path() const {
|
||||
return backend_->Path();
|
||||
}
|
||||
|
||||
size_t CachingFileLoader::ReadAt(s64 absolutePos, size_t bytes, void *data, Flags flags) {
|
||||
Prepare();
|
||||
if (absolutePos >= filesize_) {
|
||||
@ -288,11 +282,3 @@ void CachingFileLoader::StartReadAhead(s64 pos) {
|
||||
});
|
||||
th.detach();
|
||||
}
|
||||
|
||||
bool CachingFileLoader::IsRemote() {
|
||||
return backend_->IsRemote();
|
||||
}
|
||||
|
||||
void CachingFileLoader::Cancel() {
|
||||
backend_->Cancel();
|
||||
}
|
||||
|
@ -23,25 +23,21 @@
|
||||
#include "Common/CommonTypes.h"
|
||||
#include "Core/Loaders.h"
|
||||
|
||||
class CachingFileLoader : public FileLoader {
|
||||
class CachingFileLoader : public ProxiedFileLoader {
|
||||
public:
|
||||
CachingFileLoader(FileLoader *backend);
|
||||
~CachingFileLoader() override;
|
||||
|
||||
bool IsRemote() override;
|
||||
bool Exists() override;
|
||||
bool ExistsFast() override;
|
||||
bool IsDirectory() override;
|
||||
s64 FileSize() override;
|
||||
std::string Path() const override;
|
||||
|
||||
size_t ReadAt(s64 absolutePos, size_t bytes, size_t count, void *data, Flags flags = Flags::NONE) override {
|
||||
return ReadAt(absolutePos, bytes * count, data, flags) / bytes;
|
||||
}
|
||||
size_t ReadAt(s64 absolutePos, size_t bytes, void *data, Flags flags = Flags::NONE) override;
|
||||
|
||||
void Cancel() override;
|
||||
|
||||
private:
|
||||
void Prepare();
|
||||
void InitCache();
|
||||
@ -61,7 +57,6 @@ private:
|
||||
};
|
||||
|
||||
s64 filesize_ = 0;
|
||||
FileLoader *backend_;
|
||||
int exists_ = -1;
|
||||
int isDirectory_ = -1;
|
||||
u64 generation_;
|
||||
|
@ -41,12 +41,12 @@ std::mutex DiskCachingFileLoader::cachesMutex_;
|
||||
|
||||
// Takes ownership of backend.
|
||||
DiskCachingFileLoader::DiskCachingFileLoader(FileLoader *backend)
|
||||
: backend_(backend) {
|
||||
: ProxiedFileLoader(backend) {
|
||||
}
|
||||
|
||||
void DiskCachingFileLoader::Prepare() {
|
||||
std::call_once(preparedFlag_, [this]() {
|
||||
filesize_ = backend_->FileSize();
|
||||
filesize_ = ProxiedFileLoader::FileSize();
|
||||
if (filesize_ > 0) {
|
||||
InitCache();
|
||||
}
|
||||
@ -57,13 +57,11 @@ DiskCachingFileLoader::~DiskCachingFileLoader() {
|
||||
if (filesize_ > 0) {
|
||||
ShutdownCache();
|
||||
}
|
||||
// Takes ownership.
|
||||
delete backend_;
|
||||
}
|
||||
|
||||
bool DiskCachingFileLoader::Exists() {
|
||||
Prepare();
|
||||
return backend_->Exists();
|
||||
return ProxiedFileLoader::Exists();
|
||||
}
|
||||
|
||||
bool DiskCachingFileLoader::ExistsFast() {
|
||||
@ -72,19 +70,11 @@ bool DiskCachingFileLoader::ExistsFast() {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DiskCachingFileLoader::IsDirectory() {
|
||||
return backend_->IsDirectory();
|
||||
}
|
||||
|
||||
s64 DiskCachingFileLoader::FileSize() {
|
||||
Prepare();
|
||||
return filesize_;
|
||||
}
|
||||
|
||||
std::string DiskCachingFileLoader::Path() const {
|
||||
return backend_->Path();
|
||||
}
|
||||
|
||||
size_t DiskCachingFileLoader::ReadAt(s64 absolutePos, size_t bytes, void *data, Flags flags) {
|
||||
Prepare();
|
||||
size_t readSize;
|
||||
@ -115,14 +105,6 @@ size_t DiskCachingFileLoader::ReadAt(s64 absolutePos, size_t bytes, void *data,
|
||||
return readSize;
|
||||
}
|
||||
|
||||
bool DiskCachingFileLoader::IsRemote() {
|
||||
return backend_->IsRemote();
|
||||
}
|
||||
|
||||
void DiskCachingFileLoader::Cancel() {
|
||||
backend_->Cancel();
|
||||
}
|
||||
|
||||
std::vector<std::string> DiskCachingFileLoader::GetCachedPathsInUse() {
|
||||
std::lock_guard<std::mutex> guard(cachesMutex_);
|
||||
|
||||
@ -139,7 +121,7 @@ std::vector<std::string> DiskCachingFileLoader::GetCachedPathsInUse() {
|
||||
void DiskCachingFileLoader::InitCache() {
|
||||
std::lock_guard<std::mutex> guard(cachesMutex_);
|
||||
|
||||
std::string path = backend_->Path();
|
||||
std::string path = ProxiedFileLoader::Path();
|
||||
auto &entry = caches_[path];
|
||||
if (!entry) {
|
||||
entry = new DiskCachingFileLoaderCache(path, filesize_);
|
||||
@ -155,7 +137,7 @@ void DiskCachingFileLoader::ShutdownCache() {
|
||||
if (cache_->Release()) {
|
||||
// If it ran out of counts, delete it.
|
||||
delete cache_;
|
||||
caches_.erase(backend_->Path());
|
||||
caches_.erase(ProxiedFileLoader::Path());
|
||||
}
|
||||
cache_ = nullptr;
|
||||
}
|
||||
|
@ -27,25 +27,20 @@
|
||||
|
||||
class DiskCachingFileLoaderCache;
|
||||
|
||||
class DiskCachingFileLoader : public FileLoader {
|
||||
class DiskCachingFileLoader : public ProxiedFileLoader {
|
||||
public:
|
||||
DiskCachingFileLoader(FileLoader *backend);
|
||||
~DiskCachingFileLoader() override;
|
||||
|
||||
bool IsRemote() override;
|
||||
bool Exists() override;
|
||||
bool ExistsFast() override;
|
||||
bool IsDirectory() override;
|
||||
s64 FileSize() override;
|
||||
std::string Path() const override;
|
||||
|
||||
size_t ReadAt(s64 absolutePos, size_t bytes, size_t count, void *data, Flags flags = Flags::NONE) override {
|
||||
return ReadAt(absolutePos, bytes * count, data, flags) / bytes;
|
||||
}
|
||||
size_t ReadAt(s64 absolutePos, size_t bytes, void *data, Flags flags = Flags::NONE) override;
|
||||
|
||||
void Cancel() override;
|
||||
|
||||
static std::vector<std::string> GetCachedPathsInUse();
|
||||
|
||||
private:
|
||||
@ -55,7 +50,6 @@ private:
|
||||
|
||||
std::once_flag preparedFlag_;
|
||||
s64 filesize_ = 0;
|
||||
FileLoader *backend_;
|
||||
DiskCachingFileLoaderCache *cache_ = nullptr;
|
||||
|
||||
// We don't support concurrent disk cache access (we use memory cached indexes.)
|
||||
|
@ -28,17 +28,23 @@ HTTPFileLoader::HTTPFileLoader(const std::string &filename)
|
||||
void HTTPFileLoader::Prepare() {
|
||||
std::call_once(preparedFlag_, [this](){
|
||||
if (!client_.Resolve(url_.Host().c_str(), url_.Port())) {
|
||||
// TODO: Should probably set some flag?
|
||||
ERROR_LOG(LOADER, "HTTP request failed, unable to resolve: %s port %d", url_.Host().c_str(), url_.Port());
|
||||
latestError_ = "Could not connect (name not resolved)";
|
||||
return;
|
||||
}
|
||||
|
||||
client_.SetDataTimeout(20.0);
|
||||
Connect();
|
||||
if (!connected_) {
|
||||
ERROR_LOG(LOADER, "HTTP request failed, failed to connect: %s port %d", url_.Host().c_str(), url_.Port());
|
||||
latestError_ = "Could not connect (refused to connect)";
|
||||
return;
|
||||
}
|
||||
|
||||
int err = client_.SendRequest("HEAD", url_.Resource().c_str());
|
||||
if (err < 0) {
|
||||
ERROR_LOG(LOADER, "HTTP request failed, failed to send request: %s port %d", url_.Host().c_str(), url_.Port());
|
||||
latestError_ = "Could not connect (could not request data)";
|
||||
Disconnect();
|
||||
return;
|
||||
}
|
||||
@ -49,6 +55,7 @@ void HTTPFileLoader::Prepare() {
|
||||
if (code != 200) {
|
||||
// Leave size at 0, invalid.
|
||||
ERROR_LOG(LOADER, "HTTP request failed, got %03d for %s", code, filename_.c_str());
|
||||
latestError_ = "Could not connect (invalid response)";
|
||||
Disconnect();
|
||||
return;
|
||||
}
|
||||
@ -138,6 +145,7 @@ size_t HTTPFileLoader::ReadAt(s64 absolutePos, size_t bytes, void *data, Flags f
|
||||
|
||||
int err = client_.SendRequest("GET", url_.Resource().c_str(), requestHeaders, nullptr);
|
||||
if (err < 0) {
|
||||
latestError_ = "Invalid response reading data";
|
||||
Disconnect();
|
||||
return 0;
|
||||
}
|
||||
@ -147,6 +155,7 @@ size_t HTTPFileLoader::ReadAt(s64 absolutePos, size_t bytes, void *data, Flags f
|
||||
int code = client_.ReadResponseHeaders(&readbuf, responseHeaders);
|
||||
if (code != 206) {
|
||||
ERROR_LOG(LOADER, "HTTP server did not respond with range, received code=%03d", code);
|
||||
latestError_ = "Invalid response reading data";
|
||||
Disconnect();
|
||||
return 0;
|
||||
}
|
||||
@ -185,6 +194,7 @@ size_t HTTPFileLoader::ReadAt(s64 absolutePos, size_t bytes, void *data, Flags f
|
||||
|
||||
if (!supportedResponse) {
|
||||
ERROR_LOG(LOADER, "HTTP server did not respond with the range we wanted.");
|
||||
latestError_ = "Invalid response reading data";
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -48,6 +48,10 @@ public:
|
||||
cancelConnect_ = true;
|
||||
}
|
||||
|
||||
std::string LatestError() const override {
|
||||
return latestError_;
|
||||
}
|
||||
|
||||
private:
|
||||
void Prepare();
|
||||
|
||||
@ -67,6 +71,7 @@ private:
|
||||
std::string filename_;
|
||||
bool connected_ = false;
|
||||
bool cancelConnect_ = false;
|
||||
const char *latestError_ = "";
|
||||
|
||||
std::once_flag preparedFlag_;
|
||||
std::mutex readAtMutex_;
|
||||
|
@ -28,7 +28,7 @@
|
||||
|
||||
// Takes ownership of backend.
|
||||
RamCachingFileLoader::RamCachingFileLoader(FileLoader *backend)
|
||||
: backend_(backend) {
|
||||
: ProxiedFileLoader(backend) {
|
||||
filesize_ = backend->FileSize();
|
||||
if (filesize_ > 0) {
|
||||
InitCache();
|
||||
@ -39,27 +39,25 @@ RamCachingFileLoader::~RamCachingFileLoader() {
|
||||
if (filesize_ > 0) {
|
||||
ShutdownCache();
|
||||
}
|
||||
// Takes ownership.
|
||||
delete backend_;
|
||||
}
|
||||
|
||||
bool RamCachingFileLoader::Exists() {
|
||||
if (exists_ == -1) {
|
||||
exists_ = backend_->Exists() ? 1 : 0;
|
||||
exists_ = ProxiedFileLoader::Exists() ? 1 : 0;
|
||||
}
|
||||
return exists_ == 1;
|
||||
}
|
||||
|
||||
bool RamCachingFileLoader::ExistsFast() {
|
||||
if (exists_ == -1) {
|
||||
return backend_->ExistsFast();
|
||||
return ProxiedFileLoader::ExistsFast();
|
||||
}
|
||||
return exists_ == 1;
|
||||
}
|
||||
|
||||
bool RamCachingFileLoader::IsDirectory() {
|
||||
if (isDirectory_ == -1) {
|
||||
isDirectory_ = backend_->IsDirectory() ? 1 : 0;
|
||||
isDirectory_ = ProxiedFileLoader::IsDirectory() ? 1 : 0;
|
||||
}
|
||||
return isDirectory_ == 1;
|
||||
}
|
||||
@ -68,10 +66,6 @@ s64 RamCachingFileLoader::FileSize() {
|
||||
return filesize_;
|
||||
}
|
||||
|
||||
std::string RamCachingFileLoader::Path() const {
|
||||
return backend_->Path();
|
||||
}
|
||||
|
||||
size_t RamCachingFileLoader::ReadAt(s64 absolutePos, size_t bytes, void *data, Flags flags) {
|
||||
size_t readSize = 0;
|
||||
if (cache_ == nullptr || (flags & Flags::HINT_UNCACHED) != 0) {
|
||||
@ -129,7 +123,7 @@ void RamCachingFileLoader::Cancel() {
|
||||
aheadCancel_ = true;
|
||||
}
|
||||
|
||||
backend_->Cancel();
|
||||
ProxiedFileLoader::Cancel();
|
||||
}
|
||||
|
||||
size_t RamCachingFileLoader::ReadFromCache(s64 pos, size_t bytes, void *data) {
|
||||
@ -270,7 +264,3 @@ u32 RamCachingFileLoader::NextAheadBlock() {
|
||||
|
||||
return 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
bool RamCachingFileLoader::IsRemote() {
|
||||
return backend_->IsRemote();
|
||||
}
|
||||
|
@ -23,17 +23,15 @@
|
||||
#include "Common/CommonTypes.h"
|
||||
#include "Core/Loaders.h"
|
||||
|
||||
class RamCachingFileLoader : public FileLoader {
|
||||
class RamCachingFileLoader : public ProxiedFileLoader {
|
||||
public:
|
||||
RamCachingFileLoader(FileLoader *backend);
|
||||
~RamCachingFileLoader() override;
|
||||
|
||||
bool IsRemote() override;
|
||||
bool Exists() override;
|
||||
bool ExistsFast() override;
|
||||
bool IsDirectory() override;
|
||||
s64 FileSize() override;
|
||||
std::string Path() const override;
|
||||
|
||||
size_t ReadAt(s64 absolutePos, size_t bytes, size_t count, void *data, Flags flags = Flags::NONE) override {
|
||||
return ReadAt(absolutePos, bytes * count, data, flags) / bytes;
|
||||
@ -59,7 +57,6 @@ private:
|
||||
};
|
||||
|
||||
s64 filesize_ = 0;
|
||||
FileLoader *backend_;
|
||||
u8 *cache_ = nullptr;
|
||||
int exists_ = -1;
|
||||
int isDirectory_ = -1;
|
||||
|
@ -19,47 +19,38 @@
|
||||
|
||||
// Takes ownership of backend.
|
||||
RetryingFileLoader::RetryingFileLoader(FileLoader *backend)
|
||||
: backend_(backend) {
|
||||
}
|
||||
|
||||
RetryingFileLoader::~RetryingFileLoader() {
|
||||
// Takes ownership.
|
||||
delete backend_;
|
||||
: ProxiedFileLoader(backend) {
|
||||
}
|
||||
|
||||
bool RetryingFileLoader::Exists() {
|
||||
if (!backend_->Exists()) {
|
||||
if (!ProxiedFileLoader::Exists()) {
|
||||
// Retry once, immediately.
|
||||
return backend_->Exists();
|
||||
return ProxiedFileLoader::Exists();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RetryingFileLoader::ExistsFast() {
|
||||
if (!backend_->ExistsFast()) {
|
||||
if (!ProxiedFileLoader::ExistsFast()) {
|
||||
// Retry once, immediately.
|
||||
return backend_->ExistsFast();
|
||||
return ProxiedFileLoader::ExistsFast();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RetryingFileLoader::IsDirectory() {
|
||||
// Can't tell if it's an error either way.
|
||||
return backend_->IsDirectory();
|
||||
return ProxiedFileLoader::IsDirectory();
|
||||
}
|
||||
|
||||
s64 RetryingFileLoader::FileSize() {
|
||||
s64 filesize = backend_->FileSize();
|
||||
s64 filesize = ProxiedFileLoader::FileSize();
|
||||
if (filesize == 0) {
|
||||
return backend_->FileSize();
|
||||
return ProxiedFileLoader::FileSize();
|
||||
}
|
||||
return filesize;
|
||||
}
|
||||
|
||||
std::string RetryingFileLoader::Path() const {
|
||||
return backend_->Path();
|
||||
}
|
||||
|
||||
size_t RetryingFileLoader::ReadAt(s64 absolutePos, size_t bytes, void *data, Flags flags) {
|
||||
size_t readSize = backend_->ReadAt(absolutePos, bytes, data, flags);
|
||||
|
||||
@ -72,11 +63,3 @@ size_t RetryingFileLoader::ReadAt(s64 absolutePos, size_t bytes, void *data, Fla
|
||||
|
||||
return readSize;
|
||||
}
|
||||
|
||||
bool RetryingFileLoader::IsRemote() {
|
||||
return backend_->IsRemote();
|
||||
}
|
||||
|
||||
void RetryingFileLoader::Cancel() {
|
||||
backend_->Cancel();
|
||||
}
|
||||
|
@ -20,29 +20,22 @@
|
||||
#include "Common/CommonTypes.h"
|
||||
#include "Core/Loaders.h"
|
||||
|
||||
class RetryingFileLoader : public FileLoader {
|
||||
class RetryingFileLoader : public ProxiedFileLoader {
|
||||
public:
|
||||
RetryingFileLoader(FileLoader *backend);
|
||||
~RetryingFileLoader() override;
|
||||
|
||||
bool IsRemote() override;
|
||||
bool Exists() override;
|
||||
bool ExistsFast() override;
|
||||
bool IsDirectory() override;
|
||||
s64 FileSize() override;
|
||||
std::string Path() const override;
|
||||
|
||||
size_t ReadAt(s64 absolutePos, size_t bytes, size_t count, void *data, Flags flags = Flags::NONE) override {
|
||||
return ReadAt(absolutePos, bytes * count, data, flags) / bytes;
|
||||
}
|
||||
size_t ReadAt(s64 absolutePos, size_t bytes, void *data, Flags flags = Flags::NONE) override;
|
||||
|
||||
void Cancel() override;
|
||||
|
||||
private:
|
||||
enum {
|
||||
MAX_RETRIES = 3,
|
||||
};
|
||||
|
||||
FileLoader *backend_;
|
||||
};
|
||||
|
@ -294,7 +294,9 @@ bool LoadFile(FileLoader **fileLoaderPtr, std::string *error_string) {
|
||||
|
||||
case IdentifiedFileType::ERROR_IDENTIFYING:
|
||||
ERROR_LOG(LOADER, "Could not read file");
|
||||
*error_string = "Error reading file";
|
||||
*error_string = fileLoader ? fileLoader->LatestError() : "";
|
||||
if (error_string->empty())
|
||||
*error_string = "Error reading file";
|
||||
break;
|
||||
|
||||
case IdentifiedFileType::ARCHIVE_RAR:
|
||||
|
@ -93,6 +93,48 @@ public:
|
||||
// Cancel any operations that might block, if possible.
|
||||
virtual void Cancel() {
|
||||
}
|
||||
|
||||
virtual std::string LatestError() const {
|
||||
return "";
|
||||
}
|
||||
};
|
||||
|
||||
class ProxiedFileLoader : public FileLoader {
|
||||
public:
|
||||
ProxiedFileLoader(FileLoader *backend) : backend_(backend) {
|
||||
}
|
||||
~ProxiedFileLoader() override {
|
||||
// Takes ownership.
|
||||
delete backend_;
|
||||
}
|
||||
|
||||
bool IsRemote() override {
|
||||
return backend_->IsRemote();
|
||||
}
|
||||
bool Exists() override {
|
||||
return backend_->Exists();
|
||||
}
|
||||
bool ExistsFast() override {
|
||||
return backend_->ExistsFast();
|
||||
}
|
||||
bool IsDirectory() override {
|
||||
return backend_->IsDirectory();
|
||||
}
|
||||
s64 FileSize() override {
|
||||
return backend_->FileSize();
|
||||
}
|
||||
std::string Path() const override {
|
||||
return backend_->Path();
|
||||
}
|
||||
void Cancel() override {
|
||||
backend_->Cancel();
|
||||
}
|
||||
std::string LatestError() const override {
|
||||
return backend_->LatestError();
|
||||
}
|
||||
|
||||
protected:
|
||||
FileLoader *backend_;
|
||||
};
|
||||
|
||||
inline u32 operator & (const FileLoader::Flags &a, const FileLoader::Flags &b) {
|
||||
|
@ -146,8 +146,12 @@ bool Buffer::FlushToFile(const char *filename) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Buffer::FlushSocket(uintptr_t sock) {
|
||||
bool Buffer::FlushSocket(uintptr_t sock, double timeout) {
|
||||
for (size_t pos = 0, end = data_.size(); pos < end; ) {
|
||||
if (timeout >= 0.0 && !fd_util::WaitUntilReady(sock, timeout, true)) {
|
||||
ELOG("FlushSocket timed out");
|
||||
return false;
|
||||
}
|
||||
int sent = send(sock, &data_[pos], (int)(end - pos), MSG_NOSIGNAL);
|
||||
if (sent < 0) {
|
||||
ELOG("FlushSocket failed");
|
||||
@ -156,7 +160,7 @@ bool Buffer::FlushSocket(uintptr_t sock) {
|
||||
pos += sent;
|
||||
|
||||
// Buffer full, don't spin.
|
||||
if (sent == 0) {
|
||||
if (sent == 0 && timeout < 0.0) {
|
||||
sleep_ms(1);
|
||||
}
|
||||
}
|
||||
|
@ -59,12 +59,12 @@ class Buffer {
|
||||
|
||||
// Simple I/O.
|
||||
|
||||
// Writes the entire buffer to the file descriptor. Also resets the
|
||||
// size to zero. On failure, data remains in buffer and nothing is
|
||||
// written.
|
||||
// Writes the entire buffer to the file descriptor. Also resets the
|
||||
// size to zero. On failure, data remains in buffer and nothing is
|
||||
// written.
|
||||
bool Flush(int fd);
|
||||
bool FlushToFile(const char *filename);
|
||||
bool FlushSocket(uintptr_t sock); // Windows portability
|
||||
bool FlushSocket(uintptr_t sock, double timeout = -1.0); // Windows portability
|
||||
|
||||
bool ReadAll(int fd, int hintSize = 0);
|
||||
bool ReadAllWithProgress(int fd, int knownSize, float *progress, bool *cancelled);
|
||||
|
@ -283,7 +283,7 @@ int Client::SendRequestWithData(const char *method, const char *resource, const
|
||||
userAgent_,
|
||||
otherHeaders ? otherHeaders : "");
|
||||
buffer.Append(data);
|
||||
bool flushed = buffer.FlushSocket(sock());
|
||||
bool flushed = buffer.FlushSocket(sock(), dataTimeout_);
|
||||
if (!flushed) {
|
||||
return -1; // TODO error code.
|
||||
}
|
||||
@ -292,6 +292,10 @@ int Client::SendRequestWithData(const char *method, const char *resource, const
|
||||
|
||||
int Client::ReadResponseHeaders(Buffer *readbuf, std::vector<std::string> &responseHeaders, float *progress) {
|
||||
// Snarf all the data we can into RAM. A little unsafe but hey.
|
||||
if (dataTimeout_ >= 0.0 && fd_util::WaitUntilReady(sock(), dataTimeout_, false)) {
|
||||
ELOG("HTTP headers timed out");
|
||||
return -1;
|
||||
}
|
||||
if (readbuf->Read(sock(), 4096) < 0) {
|
||||
ELOG("Failed to read HTTP headers :(");
|
||||
return -1;
|
||||
|
@ -75,8 +75,14 @@ public:
|
||||
// If your response contains a response, you must read it.
|
||||
int ReadResponseEntity(Buffer *readbuf, const std::vector<std::string> &responseHeaders, Buffer *output, float *progress = nullptr, bool *cancelled = nullptr);
|
||||
|
||||
void SetDataTimeout(double t) {
|
||||
dataTimeout_ = t;
|
||||
}
|
||||
|
||||
protected:
|
||||
const char *userAgent_;
|
||||
const char *httpVersion_;
|
||||
double dataTimeout_ = -1.0;
|
||||
};
|
||||
|
||||
// Not particularly efficient, but hey - it's a background download, that's pretty cool :P
|
||||
|
Loading…
Reference in New Issue
Block a user