| 401 | } |
| 402 | |
| 403 | void HttpDataStream::ThreadProc() { |
| 404 | if (this->curlEasy) { |
| 405 | static const int kMaxRetries = 10; |
| 406 | int retryCount = 0; /* note: weighted based on failure type */ |
| 407 | while (this->state != State::Downloaded && !this->interrupted) { |
| 408 | auto const curlCode = curl_easy_perform(this->curlEasy); |
| 409 | long httpStatusCode = 0; |
| 410 | curl_easy_getinfo(this->curlEasy, CURLINFO_RESPONSE_CODE, &httpStatusCode); |
| 411 | if (httpStatusCode == 200) { |
| 412 | this->state = curlCode != CURLE_OK |
| 413 | ? State::Aborted |
| 414 | : State::Downloaded; |
| 415 | |
| 416 | if (this->reader) { |
| 417 | if (this->written > 0) { |
| 418 | this->reader->Add(this->written); |
| 419 | this->written = 0; |
| 420 | } |
| 421 | this->reader->Completed(); |
| 422 | } |
| 423 | } |
| 424 | else { |
| 425 | if (httpStatusCode == 429) { /* too many requests */ |
| 426 | this->state = State::Retrying; |
| 427 | retryCount += 1; |
| 428 | sleepMs(5000); |
| 429 | } |
| 430 | else if ((httpStatusCode < 400 || httpStatusCode >= 500) && retryCount < kMaxRetries) { |
| 431 | { |
| 432 | std::unique_lock<std::mutex> lock(this->stateMutex); |
| 433 | this->ResetFileHandles(); |
| 434 | } |
| 435 | this->state = State::Retrying; |
| 436 | retryCount += 2; |
| 437 | sleepMs(2000); |
| 438 | } |
| 439 | else { |
| 440 | this->state = State::Error; |
| 441 | this->interrupted = true; |
| 442 | } |
| 443 | } |
| 444 | } |
| 445 | |
| 446 | startedContition.notify_all(); /* in case the header write function was never called */ |
| 447 | |
| 448 | if (this->curlEasy) { |
| 449 | curl_easy_cleanup(this->curlEasy); |
| 450 | this->curlEasy = nullptr; |
| 451 | } |
| 452 | |
| 453 | if (this->curlHeaders) { |
| 454 | curl_slist_free_all(this->curlHeaders); |
| 455 | this->curlHeaders = nullptr; |
| 456 | } |
| 457 | |
| 458 | if (this->writeFile) { |
| 459 | fclose(this->writeFile); |
| 460 | this->writeFile = nullptr; |
nothing calls this directly
no test coverage detected