Improve response time to cancellation in cURL downloads.

This commit is contained in:
Steveice10 2019-01-01 10:53:01 -08:00
parent 6a5f6adafa
commit 2fead09671
3 changed files with 43 additions and 31 deletions

View File

@ -278,6 +278,7 @@ typedef struct {
u64* contentLength; u64* contentLength;
void* userData; void* userData;
Result (*callback)(void* userData, void* buffer, size_t size); Result (*callback)(void* userData, void* buffer, size_t size);
Result (*checkRunning)(void* userData);
void* buf; void* buf;
u32 pos; u32 pos;
@ -312,6 +313,10 @@ static size_t http_curl_header_callback(char* buffer, size_t size, size_t nitems
static size_t http_curl_write_callback(char* ptr, size_t size, size_t nmemb, void* userdata) { static size_t http_curl_write_callback(char* ptr, size_t size, size_t nmemb, void* userdata) {
http_curl_data* curlData = (http_curl_data*) userdata; http_curl_data* curlData = (http_curl_data*) userdata;
if(curlData->checkRunning != NULL && R_FAILED(curlData->res = curlData->checkRunning(curlData->userData))) {
return 0;
}
size_t srcPos = 0; size_t srcPos = 0;
size_t available = size * nmemb; size_t available = size * nmemb;
while(available > 0) { while(available > 0) {
@ -333,7 +338,8 @@ static size_t http_curl_write_callback(char* ptr, size_t size, size_t nmemb, voi
return R_SUCCEEDED(curlData->res) ? size * nmemb : 0; return R_SUCCEEDED(curlData->res) ? size * nmemb : 0;
} }
Result http_download_callback(const char* url, u32 bufferSize, u64* contentLength, void* userData, Result (*callback)(void* userData, void* buffer, size_t size)) { Result http_download_callback(const char* url, u32 bufferSize, u64* contentLength, void* userData, Result (*callback)(void* userData, void* buffer, size_t size),
Result (*checkRunning)(void* userData)) {
Result res = 0; Result res = 0;
void* buf = malloc(bufferSize); void* buf = malloc(bufferSize);
@ -349,6 +355,7 @@ Result http_download_callback(const char* url, u32 bufferSize, u64* contentLengt
u32 total = 0; u32 total = 0;
u32 currSize = 0; u32 currSize = 0;
while(total < dlSize while(total < dlSize
&& (checkRunning == NULL || R_SUCCEEDED(res = checkRunning(userData)))
&& R_SUCCEEDED(res = http_read(context, &currSize, buf, bufferSize)) && R_SUCCEEDED(res = http_read(context, &currSize, buf, bufferSize))
&& R_SUCCEEDED(res = callback(userData, buf, currSize))) { && R_SUCCEEDED(res = callback(userData, buf, currSize))) {
total += currSize; total += currSize;
@ -364,7 +371,7 @@ Result http_download_callback(const char* url, u32 bufferSize, u64* contentLengt
CURL* curl = curl_easy_init(); CURL* curl = curl_easy_init();
if(curl != NULL) { if(curl != NULL) {
http_curl_data curlData = {bufferSize, contentLength, userData, callback, buf, 0, 0}; http_curl_data curlData = {bufferSize, contentLength, userData, callback, checkRunning, buf, 0, 0};
curl_easy_setopt(curl, CURLOPT_URL, url); curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_USERAGENT, HTTP_USER_AGENT); curl_easy_setopt(curl, CURLOPT_USERAGENT, HTTP_USER_AGENT);
@ -445,7 +452,7 @@ static Result http_download_buffer_callback(void* userData, void* buffer, size_t
Result http_download_buffer(const char* url, u32* downloadedSize, void* buf, size_t size) { Result http_download_buffer(const char* url, u32* downloadedSize, void* buf, size_t size) {
http_buffer_data data = {buf, size, 0}; http_buffer_data data = {buf, size, 0};
Result res = http_download_callback(url, size, NULL, &data, http_download_buffer_callback); Result res = http_download_callback(url, size, NULL, &data, http_download_buffer_callback, NULL);
if(R_SUCCEEDED(res)) { if(R_SUCCEEDED(res)) {
*downloadedSize = data.pos; *downloadedSize = data.pos;

View File

@ -9,7 +9,8 @@ Result http_get_size(http_context context, u32* size);
Result http_get_file_name(http_context context, char* out, u32 size); Result http_get_file_name(http_context context, char* out, u32 size);
Result http_read(http_context context, u32* bytesRead, void* buffer, u32 size); Result http_read(http_context context, u32* bytesRead, void* buffer, u32 size);
Result http_download_callback(const char* url, u32 bufferSize, u64* contentLength, void* userData, Result (*callback)(void* userData, void* buffer, size_t size)); Result http_download_callback(const char* url, u32 bufferSize, u64* contentLength, void* userData, Result (*callback)(void* userData, void* buffer, size_t size),
Result (*checkRunning)(void* userData));
Result http_download_buffer(const char* url, u32* downloadedSize, void* buf, size_t size); Result http_download_buffer(const char* url, u32* downloadedSize, void* buf, size_t size);
Result http_download_json(const char* url, json_t** json, size_t maxSize); Result http_download_json(const char* url, json_t** json, size_t maxSize);
Result http_download_seed(u64 titleId); Result http_download_seed(u64 titleId);

View File

@ -155,44 +155,48 @@ static Result task_data_op_download_callback(void* userData, void* buffer, size_
Result res = 0; Result res = 0;
if(R_SUCCEEDED(res = task_data_op_check_running(data))) { if(downloadData->firstRun) {
if(downloadData->firstRun) { downloadData->firstRun = false;
downloadData->firstRun = false;
if(R_FAILED(res = data->openDst(data->data, downloadData->index, buffer, data->currTotal, &downloadData->dstHandle))) { if(R_FAILED(res = data->openDst(data->data, downloadData->index, buffer, data->currTotal, &downloadData->dstHandle))) {
return res; return res;
}
} }
}
u32 bytesWritten = 0; u32 bytesWritten = 0;
if(R_SUCCEEDED(res = data->writeDst(data->data, downloadData->dstHandle, &bytesWritten, buffer, data->currProcessed, size))) { if(R_SUCCEEDED(res = data->writeDst(data->data, downloadData->dstHandle, &bytesWritten, buffer, data->currProcessed, size))) {
data->currProcessed += bytesWritten; data->currProcessed += bytesWritten;
downloadData->bytesSinceUpdate += bytesWritten; downloadData->bytesSinceUpdate += bytesWritten;
u64 time = osGetTime(); u64 time = osGetTime();
u64 elapsed = time - downloadData->lastBytesPerSecondUpdate; u64 elapsed = time - downloadData->lastBytesPerSecondUpdate;
if(elapsed >= 1000) { if(elapsed >= 1000) {
data->bytesPerSecond = (u32) (downloadData->bytesSinceUpdate / (elapsed / 1000.0f)); data->bytesPerSecond = (u32) (downloadData->bytesSinceUpdate / (elapsed / 1000.0f));
if(downloadData->ioStartTime != 0) { if(downloadData->ioStartTime != 0) {
data->estimatedRemainingSeconds = (u32) ((data->currTotal - data->currProcessed) / (data->currProcessed / ((time - downloadData->ioStartTime) / 1000.0f))); data->estimatedRemainingSeconds = (u32) ((data->currTotal - data->currProcessed) / (data->currProcessed / ((time - downloadData->ioStartTime) / 1000.0f)));
} else { } else {
data->estimatedRemainingSeconds = 0; data->estimatedRemainingSeconds = 0;
}
if(downloadData->ioStartTime == 0 && data->currProcessed > 0) {
downloadData->ioStartTime = time;
}
downloadData->bytesSinceUpdate = 0;
downloadData->lastBytesPerSecondUpdate = time;
} }
if(downloadData->ioStartTime == 0 && data->currProcessed > 0) {
downloadData->ioStartTime = time;
}
downloadData->bytesSinceUpdate = 0;
downloadData->lastBytesPerSecondUpdate = time;
} }
} }
return res; return res;
} }
static Result task_data_op_download_check_running(void* userData) {
data_op_download_data* downloadData = (data_op_download_data*) userData;
return task_data_op_check_running(downloadData->data);
}
static Result task_data_op_download(data_op_data* data, u32 index) { static Result task_data_op_download(data_op_data* data, u32 index) {
data->currProcessed = 0; data->currProcessed = 0;
data->currTotal = 0; data->currTotal = 0;
@ -205,7 +209,7 @@ static Result task_data_op_download(data_op_data* data, u32 index) {
char url[DOWNLOAD_URL_MAX]; char url[DOWNLOAD_URL_MAX];
if(R_SUCCEEDED(res = data->getSrcUrl(data->data, index, url, DOWNLOAD_URL_MAX))) { if(R_SUCCEEDED(res = data->getSrcUrl(data->data, index, url, DOWNLOAD_URL_MAX))) {
data_op_download_data downloadData = {data, index, 0, true, 0, osGetTime(), 0}; data_op_download_data downloadData = {data, index, 0, true, 0, osGetTime(), 0};
res = http_download_callback(url, data->bufferSize, &data->currTotal, &downloadData, task_data_op_download_callback); res = http_download_callback(url, data->bufferSize, &data->currTotal, &downloadData, task_data_op_download_callback, task_data_op_download_check_running);
if(downloadData.dstHandle != 0) { if(downloadData.dstHandle != 0) {
Result closeDstRes = data->closeDst(data->data, index, res == 0, downloadData.dstHandle); Result closeDstRes = data->closeDst(data->data, index, res == 0, downloadData.dstHandle);