diff --git a/Common/Crypto/md5.cpp b/Common/Crypto/md5.cpp index 22a83956563f..cce49809dce7 100644 --- a/Common/Crypto/md5.cpp +++ b/Common/Crypto/md5.cpp @@ -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]; diff --git a/Common/Crypto/md5.h b/Common/Crypto/md5.h index a69024d1163a..da522c34d55f 100644 --- a/Common/Crypto/md5.h +++ b/Common/Crypto/md5.h @@ -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 } diff --git a/Common/Net/HTTPClient.cpp b/Common/Net/HTTPClient.cpp index 7ef0c15df1b0..e8d3b6c7f54e 100644 --- a/Common/Net/HTTPClient.cpp +++ b/Common/Net/HTTPClient.cpp @@ -458,8 +458,8 @@ int Client::ReadResponseEntity(net::Buffer *readbuf, const std::vector Downloader::StartDownload(const std::string &url, const Path &outfile, const char *acceptMime) { - std::shared_ptr dl(new Download(url, outfile)); + std::shared_ptr 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 Downloader::StartDownloadWithCallback( const Path &outfile, std::function callback, const char *acceptMime) { - std::shared_ptr dl(new Download(url, outfile)); + std::shared_ptr 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 Downloader::AsyncPostWithCallback( + const std::string &url, + const std::string &postData, + const std::string &postMime, + std::function callback) { + std::shared_ptr 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 Downloader::GetCurrentProgress() { std::vector progress; for (size_t i = 0; i < downloads_.size(); i++) { diff --git a/Common/Net/HTTPClient.h b/Common/Net/HTTPClient.h index cafe4b08c5bc..eb1338cabc83 100644 --- a/Common/Net/HTTPClient.h +++ b/Common/Net/HTTPClient.h @@ -97,10 +97,15 @@ class Client : public net::Connection { 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 @@ class Download { 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 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 @@ class Downloader { std::function callback, const char *acceptMime = nullptr); + std::shared_ptr 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 callback); + // Drops finished downloads from the list. void Update(); void CancelAll(); + void WaitForAll(); + std::vector GetCurrentProgress(); private: std::vector> downloads_; + // These get copied to downloads_ in Update(). It's so that callbacks can add new downloads + // while running. + std::vector> newDownloads_; }; } // http diff --git a/Core/HLE/sceMd5.cpp b/Core/HLE/sceMd5.cpp index cd71adcd8499..286294d2f004 100644 --- a/Core/HLE/sceMd5.cpp +++ b/Core/HLE/sceMd5.cpp @@ -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; }