Merge pull request #17594 from hrydgard/backport-fixes

Port some fixes/improvements from the retroachievements branch
This commit is contained in:
Unknown W. Brackets 2023-06-17 14:39:22 -07:00 committed by GitHub
commit 0fb7d6f7d7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 110 additions and 62 deletions

View File

@ -62,7 +62,7 @@
/*
* MD5 context setup
*/
void md5_starts( md5_context *ctx )
void ppsspp_md5_starts( md5_context *ctx )
{
ctx->total[0] = 0;
ctx->total[1] = 0;
@ -73,7 +73,7 @@ void md5_starts( md5_context *ctx )
ctx->state[3] = 0x10325476;
}
static void md5_process( md5_context *ctx, unsigned char data[64] )
static void ppsspp_md5_process( md5_context *ctx, unsigned char data[64] )
{
unsigned long X[16], A, B, C, D;
@ -199,7 +199,7 @@ static void md5_process( md5_context *ctx, unsigned char data[64] )
/*
* MD5 process buffer
*/
void md5_update( md5_context *ctx, unsigned char *input, int ilen )
void ppsspp_md5_update( md5_context *ctx, unsigned char *input, int ilen )
{
int fill;
unsigned long left;
@ -220,7 +220,7 @@ void md5_update( md5_context *ctx, unsigned char *input, int ilen )
{
memcpy( (void *) (ctx->buffer + left),
(void *) input, fill );
md5_process( ctx, ctx->buffer );
ppsspp_md5_process( ctx, ctx->buffer );
input += fill;
ilen -= fill;
left = 0;
@ -228,7 +228,7 @@ void md5_update( md5_context *ctx, unsigned char *input, int ilen )
while( ilen >= 64 )
{
md5_process( ctx, input );
ppsspp_md5_process( ctx, input );
input += 64;
ilen -= 64;
}
@ -251,7 +251,7 @@ static const unsigned char md5_padding[64] =
/*
* MD5 final digest
*/
void md5_finish( md5_context *ctx, unsigned char output[16] )
void ppsspp_md5_finish( md5_context *ctx, unsigned char output[16] )
{
unsigned long last, padn;
unsigned long high, low;
@ -267,8 +267,8 @@ void md5_finish( md5_context *ctx, unsigned char output[16] )
last = ctx->total[0] & 0x3F;
padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
md5_update( ctx, (unsigned char *) md5_padding, padn );
md5_update( ctx, msglen, 8 );
ppsspp_md5_update( ctx, (unsigned char *) md5_padding, padn );
ppsspp_md5_update( ctx, msglen, 8 );
PUT_ULONG_LE( ctx->state[0], output, 0 );
PUT_ULONG_LE( ctx->state[1], output, 4 );
@ -279,13 +279,13 @@ void md5_finish( md5_context *ctx, unsigned char output[16] )
/*
* output = MD5( input buffer )
*/
void md5( unsigned char *input, int ilen, unsigned char output[16] )
void ppsspp_md5( unsigned char *input, int ilen, unsigned char output[16] )
{
md5_context ctx;
md5_starts( &ctx );
md5_update( &ctx, input, ilen );
md5_finish( &ctx, output );
ppsspp_md5_starts( &ctx );
ppsspp_md5_update( &ctx, input, ilen );
ppsspp_md5_finish( &ctx, output );
memset( &ctx, 0, sizeof( md5_context ) );
}
@ -293,14 +293,14 @@ void md5( unsigned char *input, int ilen, unsigned char output[16] )
/*
* MD5 HMAC context setup
*/
void md5_hmac_starts( md5_context *ctx, unsigned char *key, int keylen )
void ppsspp_md5_hmac_starts( md5_context *ctx, unsigned char *key, int keylen )
{
int i;
unsigned char sum[16];
if( keylen > 64 )
{
md5( key, keylen, sum );
ppsspp_md5( key, keylen, sum );
keylen = 16;
key = sum;
}
@ -314,8 +314,8 @@ void md5_hmac_starts( md5_context *ctx, unsigned char *key, int keylen )
ctx->opad[i] = (unsigned char)( ctx->opad[i] ^ key[i] );
}
md5_starts( ctx );
md5_update( ctx, ctx->ipad, 64 );
ppsspp_md5_starts( ctx );
ppsspp_md5_update( ctx, ctx->ipad, 64 );
memset( sum, 0, sizeof( sum ) );
}
@ -323,23 +323,23 @@ void md5_hmac_starts( md5_context *ctx, unsigned char *key, int keylen )
/*
* MD5 HMAC process buffer
*/
void md5_hmac_update( md5_context *ctx, unsigned char *input, int ilen )
void ppsspp_md5_hmac_update( md5_context *ctx, unsigned char *input, int ilen )
{
md5_update( ctx, input, ilen );
ppsspp_md5_update( ctx, input, ilen );
}
/*
* MD5 HMAC final digest
*/
void md5_hmac_finish( md5_context *ctx, unsigned char output[16] )
void ppsspp_md5_hmac_finish( md5_context *ctx, unsigned char output[16] )
{
unsigned char tmpbuf[16];
md5_finish( ctx, tmpbuf );
md5_starts( ctx );
md5_update( ctx, ctx->opad, 64 );
md5_update( ctx, tmpbuf, 16 );
md5_finish( ctx, output );
ppsspp_md5_finish( ctx, tmpbuf );
ppsspp_md5_starts( ctx );
ppsspp_md5_update( ctx, ctx->opad, 64 );
ppsspp_md5_update( ctx, tmpbuf, 16 );
ppsspp_md5_finish( ctx, output );
memset( tmpbuf, 0, sizeof( tmpbuf ) );
}
@ -347,14 +347,14 @@ void md5_hmac_finish( md5_context *ctx, unsigned char output[16] )
/*
* output = HMAC-MD5( hmac key, input buffer )
*/
void md5_hmac( unsigned char *key, int keylen, unsigned char *input, int ilen,
void ppsspp_md5_hmac( unsigned char *key, int keylen, unsigned char *input, int ilen,
unsigned char output[16] )
{
md5_context ctx;
md5_hmac_starts( &ctx, key, keylen );
md5_hmac_update( &ctx, input, ilen );
md5_hmac_finish( &ctx, output );
ppsspp_md5_hmac_starts( &ctx, key, keylen );
ppsspp_md5_hmac_update( &ctx, input, ilen );
ppsspp_md5_hmac_finish( &ctx, output );
memset( &ctx, 0, sizeof( md5_context ) );
}
@ -464,7 +464,7 @@ static const unsigned char md5_hmac_test_sum[7][16] =
/*
* Checkup routine
*/
int md5_self_test( int verbose )
int ppsspp_md5_self_test( int verbose )
{
int i, buflen;
unsigned char buf[1024];

View File

@ -46,7 +46,7 @@ extern "C" {
*
* \param ctx context to be initialized
*/
void md5_starts( md5_context *ctx );
void ppsspp_md5_starts( md5_context *ctx );
/**
* \brief MD5 process buffer
@ -55,7 +55,7 @@ void md5_starts( md5_context *ctx );
* \param input buffer holding the data
* \param ilen length of the input data
*/
void md5_update( md5_context *ctx, unsigned char *input, int ilen );
void ppsspp_md5_update( md5_context *ctx, unsigned char *input, int ilen );
/**
* \brief MD5 final digest
@ -63,7 +63,7 @@ void md5_update( md5_context *ctx, unsigned char *input, int ilen );
* \param ctx MD5 context
* \param output MD5 checksum result
*/
void md5_finish( md5_context *ctx, unsigned char output[16] );
void ppsspp_md5_finish( md5_context *ctx, unsigned char output[16] );
/**
* \brief Output = MD5( input buffer )
@ -72,7 +72,7 @@ void md5_finish( md5_context *ctx, unsigned char output[16] );
* \param ilen length of the input data
* \param output MD5 checksum result
*/
void md5( unsigned char *input, int ilen, unsigned char output[16] );
void ppsspp_md5( unsigned char *input, int ilen, unsigned char output[16] );
/**
* \brief Output = MD5( file contents )
@ -83,7 +83,7 @@ void md5( unsigned char *input, int ilen, unsigned char output[16] );
* \return 0 if successful, 1 if fopen failed,
* or 2 if fread failed
*/
int md5_file( char *path, unsigned char output[16] );
int ppsspp_md5_file( char *path, unsigned char output[16] );
/**
* \brief MD5 HMAC context setup
@ -92,7 +92,7 @@ int md5_file( char *path, unsigned char output[16] );
* \param key HMAC secret key
* \param keylen length of the HMAC key
*/
void md5_hmac_starts( md5_context *ctx, unsigned char *key, int keylen );
void ppsspp_md5_hmac_starts( md5_context *ctx, unsigned char *key, int keylen );
/**
* \brief MD5 HMAC process buffer
@ -101,7 +101,7 @@ void md5_hmac_starts( md5_context *ctx, unsigned char *key, int keylen );
* \param input buffer holding the data
* \param ilen length of the input data
*/
void md5_hmac_update( md5_context *ctx, unsigned char *input, int ilen );
void ppsspp_md5_hmac_update( md5_context *ctx, unsigned char *input, int ilen );
/**
* \brief MD5 HMAC final digest
@ -109,7 +109,7 @@ void md5_hmac_update( md5_context *ctx, unsigned char *input, int ilen );
* \param ctx HMAC context
* \param output MD5 HMAC checksum result
*/
void md5_hmac_finish( md5_context *ctx, unsigned char output[16] );
void ppsspp_md5_hmac_finish( md5_context *ctx, unsigned char output[16] );
/**
* \brief Output = HMAC-MD5( hmac key, input buffer )
@ -120,7 +120,7 @@ void md5_hmac_finish( md5_context *ctx, unsigned char output[16] );
* \param ilen length of the input data
* \param output HMAC-MD5 result
*/
void md5_hmac( unsigned char *key, int keylen,
void ppsspp_md5_hmac( unsigned char *key, int keylen,
unsigned char *input, int ilen,
unsigned char output[16] );
@ -129,7 +129,7 @@ void md5_hmac( unsigned char *key, int keylen,
*
* \return 0 if successful, or 1 if the test failed
*/
int md5_self_test( int verbose );
int ppsspp_md5_self_test( int verbose );
#ifdef __cplusplus
}

View File

@ -458,8 +458,8 @@ int Client::ReadResponseEntity(net::Buffer *readbuf, const std::vector<std::stri
return 0;
}
Download::Download(const std::string &url, const Path &outfile)
: progress_(&cancelled_), url_(url), outfile_(outfile) {
Download::Download(RequestMethod method, const std::string &url, const std::string &postData, const std::string &postMime, const Path &outfile)
: method_(method), progress_(&cancelled_), url_(url), postData_(postData), postMime_(postMime), outfile_(outfile) {
}
Download::~Download() {
@ -484,7 +484,7 @@ void Download::SetFailed(int code) {
completed_ = true;
}
int Download::PerformGET(const std::string &url) {
int Download::Perform(const std::string &url) {
Url fileUrl(url);
if (!fileUrl.Valid()) {
return -1;
@ -510,7 +510,11 @@ int Download::PerformGET(const std::string &url) {
}
RequestParams req(fileUrl.Resource(), acceptMime_);
return client.GET(req, &buffer_, responseHeaders_, &progress_);
if (method_ == RequestMethod::GET) {
return client.GET(req, &buffer_, responseHeaders_, &progress_);
} else {
return client.POST(req, postData_, postMime_, &buffer_, &progress_);
}
}
std::string Download::RedirectLocation(const std::string &baseUrl) {
@ -533,7 +537,7 @@ void Download::Do() {
std::string downloadURL = url_;
while (resultCode_ == 0) {
int resultCode = PerformGET(downloadURL);
int resultCode = Perform(downloadURL);
if (resultCode == -1) {
SetFailed(resultCode);
return;
@ -557,12 +561,12 @@ void Download::Do() {
}
if (resultCode == 200) {
INFO_LOG(IO, "Completed downloading %s to %s", url_.c_str(), outfile_.empty() ? "memory" : outfile_.c_str());
INFO_LOG(IO, "Completed requesting %s (storing result to %s)", url_.c_str(), outfile_.empty() ? "memory" : outfile_.c_str());
if (!outfile_.empty() && !buffer_.FlushToFile(outfile_)) {
ERROR_LOG(IO, "Failed writing download to '%s'", outfile_.c_str());
}
} else {
ERROR_LOG(IO, "Error downloading '%s' to '%s': %i", url_.c_str(), outfile_.c_str(), resultCode);
ERROR_LOG(IO, "Error requesting '%s' (storing result to '%s'): %i", url_.c_str(), outfile_.empty() ? "memory" : outfile_.c_str(), resultCode);
}
resultCode_ = resultCode;
}
@ -575,10 +579,10 @@ void Download::Do() {
}
std::shared_ptr<Download> Downloader::StartDownload(const std::string &url, const Path &outfile, const char *acceptMime) {
std::shared_ptr<Download> dl(new Download(url, outfile));
std::shared_ptr<Download> dl(new Download(RequestMethod::GET, url, "", "", outfile));
if (acceptMime)
dl->SetAccept(acceptMime);
downloads_.push_back(dl);
newDownloads_.push_back(dl);
dl->Start();
return dl;
}
@ -588,19 +592,36 @@ std::shared_ptr<Download> Downloader::StartDownloadWithCallback(
const Path &outfile,
std::function<void(Download &)> callback,
const char *acceptMime) {
std::shared_ptr<Download> dl(new Download(url, outfile));
std::shared_ptr<Download> dl(new Download(RequestMethod::GET, url, "", "", outfile));
if (acceptMime)
dl->SetAccept(acceptMime);
dl->SetCallback(callback);
downloads_.push_back(dl);
newDownloads_.push_back(dl);
dl->Start();
return dl;
}
std::shared_ptr<Download> Downloader::AsyncPostWithCallback(
const std::string &url,
const std::string &postData,
const std::string &postMime,
std::function<void(Download &)> callback) {
std::shared_ptr<Download> dl(new Download(RequestMethod::POST, url, postData, postMime, Path()));
dl->SetCallback(callback);
newDownloads_.push_back(dl);
dl->Start();
return dl;
}
void Downloader::Update() {
for (auto iter : newDownloads_) {
downloads_.push_back(iter);
}
newDownloads_.clear();
restart:
for (size_t i = 0; i < downloads_.size(); i++) {
auto &dl = downloads_[i];
auto dl = downloads_[i];
if (dl->Done()) {
dl->RunCallback();
dl->Join();
@ -610,6 +631,14 @@ void Downloader::Update() {
}
}
void Downloader::WaitForAll() {
// TODO: Should lock? Though, OK if called from main thread, where Update() is called from.
while (!downloads_.empty()) {
Update();
sleep_ms(10);
}
}
std::vector<float> Downloader::GetCurrentProgress() {
std::vector<float> progress;
for (size_t i = 0; i < downloads_.size(); i++) {

View File

@ -97,10 +97,15 @@ protected:
double dataTimeout_ = 900.0;
};
// Not particularly efficient, but hey - it's a background download, that's pretty cool :P
enum class RequestMethod {
GET,
POST,
};
// Really an asynchronous request.
class Download {
public:
Download(const std::string &url, const Path &outfile);
Download(RequestMethod method, const std::string &url, const std::string &postData, const std::string &postMime, const Path &outfile);
~Download();
void Start();
@ -154,17 +159,20 @@ public:
private:
void Do(); // Actually does the download. Runs on thread.
int PerformGET(const std::string &url);
int Perform(const std::string &url);
std::string RedirectLocation(const std::string &baseUrl);
void SetFailed(int code);
RequestProgress progress_;
RequestMethod method_;
std::string postData_;
Buffer buffer_;
std::vector<std::string> responseHeaders_;
std::string url_;
Path outfile_;
std::thread thread_;
const char *acceptMime_ = "*/*";
std::string postMime_;
int resultCode_ = 0;
bool completed_ = false;
bool failed_ = false;
@ -190,14 +198,25 @@ public:
std::function<void(Download &)> callback,
const char *acceptMime = nullptr);
std::shared_ptr<Download> AsyncPostWithCallback(
const std::string &url,
const std::string &postData,
const std::string &postMime, // Use postMime = "application/x-www-form-urlencoded" for standard form-style posts, such as used by retroachievements. For encoding form data manually we have MultipartFormDataEncoder.
std::function<void(Download &)> callback);
// Drops finished downloads from the list.
void Update();
void CancelAll();
void WaitForAll();
std::vector<float> GetCurrentProgress();
private:
std::vector<std::shared_ptr<Download>> downloads_;
// These get copied to downloads_ in Update(). It's so that callbacks can add new downloads
// while running.
std::vector<std::shared_ptr<Download>> newDownloads_;
};
} // http

View File

@ -57,7 +57,7 @@ static int sceMd5Digest(u32 dataAddr, u32 len, u32 digestAddr) {
if (!Memory::IsValidAddress(dataAddr) || !Memory::IsValidAddress(digestAddr))
return -1;
md5(Memory::GetPointerWriteUnchecked(dataAddr), (int)len, Memory::GetPointerWriteUnchecked(digestAddr));
ppsspp_md5(Memory::GetPointerWriteUnchecked(dataAddr), (int)len, Memory::GetPointerWriteUnchecked(digestAddr));
return 0;
}
@ -69,7 +69,7 @@ static int sceMd5BlockInit(u32 ctxAddr) {
// TODO: Until I know how large a context is, we just go all lazy and use a global context,
// which will work just fine unless games do several MD5 concurrently.
md5_starts(&md5_ctx);
ppsspp_md5_starts(&md5_ctx);
return 0;
}
@ -78,7 +78,7 @@ static int sceMd5BlockUpdate(u32 ctxAddr, u32 dataPtr, u32 len) {
if (!Memory::IsValidAddress(ctxAddr) || !Memory::IsValidAddress(dataPtr))
return -1;
md5_update(&md5_ctx, Memory::GetPointerWriteUnchecked(dataPtr), (int)len);
ppsspp_md5_update(&md5_ctx, Memory::GetPointerWriteUnchecked(dataPtr), (int)len);
return 0;
}
@ -87,7 +87,7 @@ static int sceMd5BlockResult(u32 ctxAddr, u32 digestAddr) {
if (!Memory::IsValidAddress(ctxAddr) || !Memory::IsValidAddress(digestAddr))
return -1;
md5_finish(&md5_ctx, Memory::GetPointerWriteUnchecked(digestAddr));
ppsspp_md5_finish(&md5_ctx, Memory::GetPointerWriteUnchecked(digestAddr));
return 0;
}
@ -97,7 +97,7 @@ int sceKernelUtilsMd5Digest(u32 dataAddr, int len, u32 digestAddr) {
if (!Memory::IsValidAddress(dataAddr) || !Memory::IsValidAddress(digestAddr))
return -1;
md5(Memory::GetPointerWriteUnchecked(dataAddr), (int)len, Memory::GetPointerWriteUnchecked(digestAddr));
ppsspp_md5(Memory::GetPointerWriteUnchecked(dataAddr), (int)len, Memory::GetPointerWriteUnchecked(digestAddr));
return 0;
}
@ -109,7 +109,7 @@ int sceKernelUtilsMd5BlockInit(u32 ctxAddr) {
// TODO: Until I know how large a context is, we just go all lazy and use a global context,
// which will work just fine unless games do several MD5 concurrently.
md5_starts(&md5_ctx);
ppsspp_md5_starts(&md5_ctx);
return 0;
}
@ -118,7 +118,7 @@ int sceKernelUtilsMd5BlockUpdate(u32 ctxAddr, u32 dataPtr, int len) {
if (!Memory::IsValidAddress(ctxAddr) || !Memory::IsValidAddress(dataPtr))
return -1;
md5_update(&md5_ctx, Memory::GetPointerWriteUnchecked(dataPtr), (int)len);
ppsspp_md5_update(&md5_ctx, Memory::GetPointerWriteUnchecked(dataPtr), (int)len);
return 0;
}
@ -127,7 +127,7 @@ int sceKernelUtilsMd5BlockResult(u32 ctxAddr, u32 digestAddr) {
if (!Memory::IsValidAddress(ctxAddr) || !Memory::IsValidAddress(digestAddr))
return -1;
md5_finish(&md5_ctx, Memory::GetPointerWriteUnchecked(digestAddr));
ppsspp_md5_finish(&md5_ctx, Memory::GetPointerWriteUnchecked(digestAddr));
return 0;
}