| 1392 | } |
| 1393 | |
| 1394 | HttpClient::RequestId HttpClient::downloadAsync(String url, String filePath, float timeout, const std::function<bool(bool interrupted, uint64_t current, uint64_t total)>& progress) { |
| 1395 | if (_stopped.load(std::memory_order_relaxed)) { |
| 1396 | progress(true, 0, 0); |
| 1397 | return 0; |
| 1398 | } |
| 1399 | if (!_downloadThread) { |
| 1400 | _downloadThread = SharedAsyncThread.newThread(); |
| 1401 | } |
| 1402 | auto request = register_http_client_request(); |
| 1403 | if (!request) { |
| 1404 | progress(true, 0, 0); |
| 1405 | return 0; |
| 1406 | } |
| 1407 | auto progressFunc = std::make_shared<std::function<bool(bool interrupted, uint64_t current, uint64_t total)>>(progress); |
| 1408 | _downloadThread->run([request, fileStr = filePath.toString(), urlStr = url.toString(), timeout, progressFunc]() -> Own<Values> { |
| 1409 | try { |
| 1410 | if (request->cancelling.load(std::memory_order_relaxed)) { |
| 1411 | SharedApplication.invokeInLogic([progressFunc]() { |
| 1412 | (*progressFunc)(true, 0, 0); |
| 1413 | }); |
| 1414 | unregister_http_client_request(request); |
| 1415 | return nullptr; |
| 1416 | } |
| 1417 | std::vector<std::string> headerNames; |
| 1418 | std::vector<std::string> headerValues; |
| 1419 | std::vector<const char*> headerNamePtrs; |
| 1420 | std::vector<const char*> headerValuePtrs; |
| 1421 | prepare_xrt_http_headers(headerNames, headerValues, headerNamePtrs, headerValuePtrs, {}); |
| 1422 | auto fullname = fileStr; |
| 1423 | SDL_RWops* out = SDL_RWFromFile(fullname.c_str(), "wb+"); |
| 1424 | if (!out) { |
| 1425 | Error("invalid local file path \"{}\" to download to", fileStr); |
| 1426 | unregister_http_client_request(request); |
| 1427 | return nullptr; |
| 1428 | } |
| 1429 | auto stream = std::shared_ptr<SDL_RWops>{out, [](SDL_RWops* io) { |
| 1430 | SDL_RWclose(io); |
| 1431 | }}; |
| 1432 | auto stopped = std::make_shared<std::atomic<bool>>(false); |
| 1433 | XrtDownloadStreamContext streamContext{request, progressFunc, stopped, out, urlStr}; |
| 1434 | int statusCode = 0; |
| 1435 | auto status = DoraXrtHttpExecuteStream( |
| 1436 | "GET", |
| 1437 | urlStr.c_str(), |
| 1438 | headerNamePtrs.data(), |
| 1439 | headerValuePtrs.data(), |
| 1440 | headerNamePtrs.size(), |
| 1441 | nullptr, |
| 1442 | 0, |
| 1443 | to_timeout_ms(timeout), |
| 1444 | 0, |
| 1445 | should_cancel_xrt_http, |
| 1446 | request.get(), |
| 1447 | on_xrt_download_stream_chunk, |
| 1448 | &streamContext, |
| 1449 | &statusCode); |
| 1450 | if (status != 0 || statusCode < 200 || statusCode >= 400 || streamContext.writeFailed || stopped->load(std::memory_order_relaxed)) { |
| 1451 | Info("failed to download \"{}\"; network status: {}, HTTP status: {}", urlStr, DoraXrtHttpStatusName(status), statusCode); |
nothing calls this directly
no test coverage detected