mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-09-22 12:26:21 +02:00
Cancel() worked on the plain HTTP path - cancelled_ is threaded down as progress->cancelled and checked while connecting and reading - but on the naett path it only set a flag that nothing looked at. The transfer ran to completion and cancelling just relabelled the result afterwards. Cancelling a store icon that scrolled away, or a homebrew download the user gave up on, kept using the bandwidth either way. naett has one hook for this: a body writer that takes less than it was given fails the request. So HTTPSRequest installs its own writer, which refuses everything once cancelled. That works on all four backends and needs nothing from naettClose, which is only really safe on Android. The catch is lifetime. The writer runs on naett's transfer thread, and a request that's still going when we're torn down would then be writing into a destroyed HTTPSRequest - which is why the buffer it writes into is a separate refcounted sink rather than a member. Join() on an unfinished request parks the sink where it won't be freed and lets the request go, so a chunk that lands afterwards writes somewhere that still exists. That path is shutdown-only: RequestManager only cancels from its destructor, and Update() waits for Done() before joining. Join now also notices a request that finished while nobody was polling, and closes it properly instead of abandoning it. What's left leaking at that point is a request still in flight as the process exits, which is what already happened, just deliberate now and logged as such rather than as an error.
52 lines
1.4 KiB
C++
52 lines
1.4 KiB
C++
#pragma once
|
|
|
|
#include <thread>
|
|
#include <string_view>
|
|
|
|
#include "Common/Net/HTTPRequest.h"
|
|
|
|
#ifndef HTTPS_NOT_AVAILABLE
|
|
|
|
#include "ext/naett-lib/naett.h"
|
|
|
|
namespace http {
|
|
|
|
// Really an asynchronous request.
|
|
class HTTPSRequest : public Request {
|
|
public:
|
|
HTTPSRequest(RequestMethod method, std::string_view url, std::string_view postData, std::string_view postMime, const Path &outfile, RequestFlags flags = RequestFlags::ProgressBar | RequestFlags::ProgressBarDelayed, std::string_view name = "");
|
|
~HTTPSRequest();
|
|
|
|
void Start() override;
|
|
void Join() override;
|
|
|
|
// Also acts as a Poll.
|
|
bool Done() override;
|
|
bool Failed() const override { return failed_; }
|
|
|
|
// Cancelling has to reach naett, or it only changes the code we report once the transfer ends
|
|
// on its own. See the .cpp.
|
|
void Cancel() override;
|
|
|
|
private:
|
|
static int WriteBodyThunk(const void *source, int bytes, void *userData);
|
|
|
|
std::string postData_;
|
|
std::string postMime_;
|
|
bool completed_ = false;
|
|
bool failed_ = false;
|
|
|
|
// Where the response body lands. Deliberately not a member of this object: naett writes into
|
|
// it from its own transfer thread, and that can outlive us if we're torn down before the
|
|
// request finishes. See NaettBodySink in the .cpp.
|
|
std::shared_ptr<struct NaettBodySink> sink_;
|
|
|
|
// Naett state
|
|
naettReq *req_ = nullptr;
|
|
naettRes *res_ = nullptr;
|
|
};
|
|
|
|
} // namespace http
|
|
|
|
#endif // HTTPS_NOT_AVAILABLE
|