• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024-2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #define MEDIA_PLUGIN
17 #define HST_LOG_TAG "Downloader"
18 
19 #include "avcodec_trace.h"
20 #include "downloader.h"
21 #include "osal/utils/steady_clock.h"
22 #include "securec.h"
23 #include "plugin/plugin_time.h"
24 #include "syspara/parameter.h"
25 
26 namespace OHOS {
27 namespace Media {
28 namespace Plugins {
29 namespace HttpPlugin {
30 namespace {
31 constexpr int PER_REQUEST_SIZE = 48 * 1024 * 10;
32 constexpr unsigned int SLEEP_TIME = 5;    // Sleep 5ms
33 constexpr size_t RETRY_TIMES = 6000;  // Retry 6000 times
34 constexpr size_t REQUEST_QUEUE_SIZE = 50;
35 constexpr long LIVE_CONTENT_LENGTH = 2147483646;
36 constexpr int32_t DOWNLOAD_LOG_FEQUENCE = 10;
37 constexpr int32_t LOOP_TIMES = 5;
38 constexpr int32_t MAX_LEN = 128;
39 const std::string USER_AGENT = "User-Agent";
40 const std::string DISPLAYVERSION = "const.product.software.version";
41 constexpr int FIRST_REQUEST_SIZE = 8 * 1024;
42 constexpr int MIN_REQUEST_SIZE = 2;
43 constexpr int SERVER_RANGE_ERROR_CODE = 416;
44 constexpr int32_t LOOP_LOG_FEQUENCE = 50;
45 constexpr int REQUEST_OFTEN_ERROR_CODE = 500;
46 constexpr int SLEEP_TEN_MICRO_SEC = 10; // 10ms
47 constexpr int APP_OPEN_RETRY_TIMES = 10;
48 }
49 
DownloadRequest(const std::string & url,DataSaveFunc saveData,StatusCallbackFunc statusCallback,bool requestWholeFile)50 DownloadRequest::DownloadRequest(const std::string& url, DataSaveFunc saveData, StatusCallbackFunc statusCallback,
51                                  bool requestWholeFile)
52     : url_(url), saveData_(std::move(saveData)), statusCallback_(std::move(statusCallback)),
53     requestWholeFile_(requestWholeFile)
54 {
55     (void)memset_s(&headerInfo_, sizeof(HeaderInfo), 0x00, sizeof(HeaderInfo));
56     headerInfo_.fileContentLen = 0;
57     headerInfo_.contentLen = 0;
58 }
59 
DownloadRequest(const std::string & url,double duration,DataSaveFunc saveData,StatusCallbackFunc statusCallback,bool requestWholeFile)60 DownloadRequest::DownloadRequest(const std::string& url,
61                                  double duration,
62                                  DataSaveFunc saveData,
63                                  StatusCallbackFunc statusCallback,
64                                  bool requestWholeFile)
65     : url_(url), duration_(duration), saveData_(std::move(saveData)), statusCallback_(std::move(statusCallback)),
66     requestWholeFile_(requestWholeFile)
67 {
68     (void)memset_s(&headerInfo_, sizeof(HeaderInfo), 0x00, sizeof(HeaderInfo));
69     headerInfo_.fileContentLen = 0;
70     headerInfo_.contentLen = 0;
71 }
72 
DownloadRequest(DataSaveFunc saveData,StatusCallbackFunc statusCallback,RequestInfo requestInfo,bool requestWholeFile)73 DownloadRequest::DownloadRequest(DataSaveFunc saveData, StatusCallbackFunc statusCallback, RequestInfo requestInfo,
74                                  bool requestWholeFile)
75     : saveData_(std::move(saveData)), statusCallback_(std::move(statusCallback)), requestInfo_(requestInfo),
76     requestWholeFile_(requestWholeFile)
77 {
78     (void)memset_s(&headerInfo_, sizeof(HeaderInfo), 0x00, sizeof(HeaderInfo));
79     headerInfo_.fileContentLen = 0;
80     headerInfo_.contentLen = 0;
81     url_ = requestInfo.url;
82     httpHeader_ = requestInfo.httpHeader;
83 }
84 
DownloadRequest(double duration,DataSaveFunc saveData,StatusCallbackFunc statusCallback,RequestInfo requestInfo,bool requestWholeFile)85 DownloadRequest::DownloadRequest(double duration,
86                                  DataSaveFunc saveData,
87                                  StatusCallbackFunc statusCallback,
88                                  RequestInfo requestInfo,
89                                  bool requestWholeFile)
90     : duration_(duration), saveData_(std::move(saveData)), statusCallback_(std::move(statusCallback)),
91     requestInfo_(requestInfo), requestWholeFile_(requestWholeFile)
92 {
93     (void)memset_s(&headerInfo_, sizeof(HeaderInfo), 0x00, sizeof(HeaderInfo));
94     headerInfo_.fileContentLen = 0;
95     headerInfo_.contentLen = 0;
96     url_ = requestInfo.url;
97     httpHeader_ = requestInfo.httpHeader;
98 }
99 
GetFileContentLength() const100 size_t DownloadRequest::GetFileContentLength() const
101 {
102     WaitHeaderUpdated();
103     return headerInfo_.GetFileContentLength();
104 }
105 
GetFileContentLengthNoWait() const106 size_t DownloadRequest::GetFileContentLengthNoWait() const
107 {
108     return headerInfo_.fileContentLen;
109 }
110 
SaveHeader(const HeaderInfo * header)111 void DownloadRequest::SaveHeader(const HeaderInfo* header)
112 {
113     MediaAVCodec::AVCodecTrace trace("DownloadRequest::SaveHeader");
114     headerInfo_.Update(header);
115     isHeaderUpdated_ = true;
116 }
117 
IsChunked(bool isInterruptNeeded)118 Seekable DownloadRequest::IsChunked(bool isInterruptNeeded)
119 {
120     isInterruptNeeded_ = isInterruptNeeded;
121     WaitHeaderUpdated();
122     if (isInterruptNeeded) {
123         MEDIA_LOG_I("Canceled");
124         return Seekable::INVALID;
125     }
126     if (headerInfo_.isChunked) {
127         return GetFileContentLength() == LIVE_CONTENT_LENGTH ? Seekable::SEEKABLE : Seekable::UNSEEKABLE;
128     } else {
129         return Seekable::SEEKABLE;
130     }
131 };
132 
IsEos() const133 bool DownloadRequest::IsEos() const
134 {
135     return isEos_;
136 }
137 
GetRetryTimes() const138 int DownloadRequest::GetRetryTimes() const
139 {
140     return retryTimes_;
141 }
142 
GetClientError() const143 int32_t DownloadRequest::GetClientError() const
144 {
145     return clientError_;
146 }
147 
GetServerError() const148 int32_t DownloadRequest::GetServerError() const
149 {
150     return serverError_;
151 }
152 
IsClosed() const153 bool DownloadRequest::IsClosed() const
154 {
155     return headerInfo_.isClosed;
156 }
157 
Close()158 void DownloadRequest::Close()
159 {
160     headerInfo_.isClosed = true;
161 }
162 
WaitHeaderUpdated() const163 void DownloadRequest::WaitHeaderUpdated() const
164 {
165     isHeaderUpdating_ = true;
166     MediaAVCodec::AVCodecTrace trace("DownloadRequest::WaitHeaderUpdated");
167     // Wait Header(fileContentLen etc.) updated
168     while (!isHeaderUpdated_ && times_ < RETRY_TIMES && !isInterruptNeeded_ && !headerInfo_.isClosed) {
169         Task::SleepInTask(SLEEP_TIME);
170         times_++;
171     }
172     MEDIA_LOG_D("isHeaderUpdated_ " PUBLIC_LOG_D32 ", times " PUBLIC_LOG_ZU ", isClosed " PUBLIC_LOG_D32,
173         isHeaderUpdated_.load(), times_.load(), headerInfo_.isClosed.load());
174     isHeaderUpdating_ = false;
175 }
176 
GetDuration() const177 double DownloadRequest::GetDuration() const
178 {
179     return duration_;
180 }
181 
SetStartTimePos(int64_t startTimePos)182 void DownloadRequest::SetStartTimePos(int64_t startTimePos)
183 {
184     startTimePos_ = startTimePos;
185     if (startTimePos_ > 0) {
186         shouldSaveData_ = false;
187     }
188 }
189 
SetRangePos(int64_t startPos,int64_t endPos)190 void DownloadRequest::SetRangePos(int64_t startPos, int64_t endPos)
191 {
192     startPos_ = startPos;
193     endPos_ = endPos;
194 }
195 
SetDownloadDoneCb(DownloadDoneCbFunc downloadDoneCallback)196 void DownloadRequest::SetDownloadDoneCb(DownloadDoneCbFunc downloadDoneCallback)
197 {
198     downloadDoneCallback_ = downloadDoneCallback;
199 }
200 
GetNowTime()201 int64_t DownloadRequest::GetNowTime()
202 {
203     return std::chrono::duration_cast<std::chrono::milliseconds>
204            (std::chrono::system_clock::now().time_since_epoch()).count();
205 }
206 
GetBitRate() const207 uint32_t DownloadRequest::GetBitRate() const
208 {
209     if ((downloadDoneTime_ == 0) || (downloadStartTime_ == 0) || (realRecvContentLen_ == 0)) {
210         return 0;
211     }
212     int64_t timeGap = downloadDoneTime_ - downloadStartTime_;
213     if (timeGap == 0) {
214         return 0;
215     }
216     uint32_t bitRate = static_cast<uint32_t>(realRecvContentLen_ * 1000 *
217                         1 * 8 / timeGap); // 1000:ms to sec 1:weight 8:byte to bit
218     return bitRate;
219 }
220 
IsChunkedVod() const221 bool DownloadRequest::IsChunkedVod() const
222 {
223     return headerInfo_.isChunked && headerInfo_.GetFileContentLength() == LIVE_CONTENT_LENGTH;
224 }
225 
IsM3u8Request() const226 bool DownloadRequest::IsM3u8Request() const
227 {
228     return protocolType_ == RequestProtocolType::HLS;
229 }
230 
SetRequestProtocolType(RequestProtocolType protocolType)231 void DownloadRequest::SetRequestProtocolType(RequestProtocolType protocolType)
232 {
233     protocolType_ = protocolType;
234 }
235 
IsServerAcceptRange() const236 bool DownloadRequest::IsServerAcceptRange() const
237 {
238     if (headerInfo_.isChunked) {
239         return false;
240     }
241     return headerInfo_.isServerAcceptRange;
242 }
243 
~DownloadRequest()244 DownloadRequest::~DownloadRequest()
245 {
246     MEDIA_LOG_D("~DownloadRequest dtor in.");
247     int sleepTmpTime = 0;
248     while (isHeaderUpdating_.load() && sleepTmpTime < RETRY_TIMES) {
249         Task::SleepInTask(SLEEP_TIME);
250         sleepTmpTime++;
251     }
252 }
253 
GetLocation(std::string & location) const254 void DownloadRequest::GetLocation(std::string& location) const
255 {
256     location = location_;
257 }
258 
Downloader(const std::string & name)259 Downloader::Downloader(const std::string& name) noexcept : name_(std::move(name))
260 {
261     shouldStartNextRequest = true;
262 
263     client_ = NetworkClient::GetInstance(&RxHeaderData, &RxBodyData, this);
264     DonwloaderInit(name);
265 }
266 
DonwloaderInit(const std::string & name)267 void Downloader::DonwloaderInit(const std::string& name)
268 {
269     client_->Init();
270     requestQue_ = std::make_shared<BlockingQueue<std::shared_ptr<DownloadRequest>>>(name_ + "RequestQue",
271         REQUEST_QUEUE_SIZE);
272     task_ = std::make_shared<Task>(std::string("OS_" + name_ + "Downloader"));
273     task_->RegisterJob([this] {
274         {
275             AutoLock lk(loopPauseMutex_);
276             if (loopStatus_ == LoopStatus::PAUSE) {
277                 MEDIA_LOG_I("0x%{public}06" PRIXPTR " loopStatus PAUSE to START", FAKE_POINTER(this));
278             }
279             loopStatus_ = LoopStatus::START;
280         }
281         HttpDownloadLoop();
282         NotifyLoopPause();
283         return 0;
284     });
285     MEDIA_LOG_I("0x%{public}06" PRIXPTR " Downloader ctor", FAKE_POINTER(this));
286 }
287 
Downloader(const std::string & name,std::shared_ptr<MediaSourceLoaderCombinations> sourceLoader)288 Downloader::Downloader(const std::string& name, std::shared_ptr<MediaSourceLoaderCombinations> sourceLoader) noexcept
289 {
290     name_ = name;
291     shouldStartNextRequest = true;
292     if (sourceLoader != nullptr) {
293         isNotBlock_ = true;
294         sourceLoader_ = sourceLoader;
295         client_ = NetworkClient::GetAppInstance(&RxHeaderData, &RxBodyData, this);
296         client_->SetLoader(sourceLoader->loader_);
297         MEDIA_LOG_I("0x%{public}06" PRIXPTR "Get app instance success", FAKE_POINTER(this));
298     } else {
299         MEDIA_LOG_I("0x%{public}06" PRIXPTR "Get libcurl instance success", FAKE_POINTER(this));
300         client_ = NetworkClient::GetInstance(&RxHeaderData, &RxBodyData, this);
301     }
302     DonwloaderInit(name);
303 }
304 
~Downloader()305 Downloader::~Downloader()
306 {
307     isDestructor_ = true;
308     MEDIA_LOG_I("~Downloader In");
309     {
310         AutoLock lock(closeMutex_);
311         if (sourceLoader_ != nullptr) {
312             sourceLoader_->Close(uuid_);
313             sourceLoader_ = nullptr;
314         }
315     }
316     Stop(false);
317     if (task_ != nullptr) {
318         task_ = nullptr;
319     }
320     if (client_ != nullptr) {
321         client_->Deinit();
322         client_ = nullptr;
323     }
324     MEDIA_LOG_I("0x%{public}06" PRIXPTR " ~Downloader dtor", FAKE_POINTER(this));
325 }
326 
Download(const std::shared_ptr<DownloadRequest> & request,int32_t waitMs)327 bool Downloader::Download(const std::shared_ptr<DownloadRequest>& request, int32_t waitMs)
328 {
329     MEDIA_LOG_I("In");
330     if (isInterruptNeeded_) {
331         request->isInterruptNeeded_ = true;
332     }
333     requestQue_->SetActive(true);
334     if (waitMs == -1) { // wait until push success
335         requestQue_->Push(request);
336         return true;
337     }
338     return requestQue_->Push(request, static_cast<int>(waitMs));
339 }
340 
Start()341 void Downloader::Start()
342 {
343     MediaAVCodec::AVCodecTrace trace("Downloader::Start");
344     MEDIA_LOG_I("start Begin");
345     requestQue_->SetActive(true);
346     task_->Start();
347     MEDIA_LOG_I("start End");
348 }
349 
Pause(bool isAsync)350 void Downloader::Pause(bool isAsync)
351 {
352     MediaAVCodec::AVCodecTrace trace("Downloader::Pause");
353     MEDIA_LOG_I("0x%{public}06" PRIXPTR " Pause Begin", FAKE_POINTER(this));
354     requestQue_->SetActive(false, false);
355     if (client_ != nullptr) {
356         isClientClose_ = true;
357         client_->Close(isAsync);
358     }
359     PauseLoop(true);
360     if (!isAsync) {
361         WaitLoopPause();
362     }
363     MEDIA_LOG_I("0x%{public}06" PRIXPTR " Pause End", FAKE_POINTER(this));
364 }
365 
Cancel()366 void Downloader::Cancel()
367 {
368     MEDIA_LOG_I("0x%{public}06" PRIXPTR " Cancel Begin", FAKE_POINTER(this));
369     if (currentRequest_ != nullptr && currentRequest_->retryTimes_ > 0) {
370         currentRequest_->retryTimes_ = 0;
371     }
372     requestQue_->SetActive(false, true);
373     shouldStartNextRequest = true;
374     if (client_ != nullptr) {
375         client_->Close(false);
376     }
377     PauseLoop(true);
378     WaitLoopPause();
379     MEDIA_LOG_I("0x%{public}06" PRIXPTR " Cancel End", FAKE_POINTER(this));
380 }
381 
382 
Resume()383 void Downloader::Resume()
384 {
385     MediaAVCodec::AVCodecTrace trace("Downloader::Resume");
386     FALSE_RETURN_MSG(!isDestructor_ && !isInterruptNeeded_, "not Resume. is Destructor or InterruptNeeded");
387     {
388         AutoLock lock(operatorMutex_);
389         MEDIA_LOG_I("resume Begin");
390         if (isClientClose_ && client_ != nullptr && currentRequest_ != nullptr) {
391             isClientClose_ = false;
392             client_->Open(currentRequest_->url_, currentRequest_->httpHeader_, currentRequest_->requestInfo_.timeoutMs);
393         }
394         requestQue_->SetActive(true);
395         if (currentRequest_ != nullptr) {
396             currentRequest_->isEos_ = false;
397 
398             int64_t fileLength = static_cast<int64_t>(currentRequest_->GetFileContentLength());
399             if (currentRequest_->startPos_ + currentRequest_->requestSize_ > fileLength) {
400                 int correctRequestSize = fileLength - currentRequest_->startPos_;
401                 MEDIA_LOG_E("resume error startPos = " PUBLIC_LOG_D64 ", requestSize = " PUBLIC_LOG_D32
402                     ", fileLength = " PUBLIC_LOG_D64 ", correct requestSize = " PUBLIC_LOG_D32,
403                     currentRequest_->startPos_, currentRequest_->requestSize_, fileLength, correctRequestSize);
404                 if (currentRequest_->startPos_ < fileLength) {
405                     currentRequest_->requestSize_ = correctRequestSize;
406                 }
407             }
408         }
409     }
410     Start();
411     MEDIA_LOG_I("resume End");
412 }
413 
Stop(bool isAsync)414 void Downloader::Stop(bool isAsync)
415 {
416     MediaAVCodec::AVCodecTrace trace("Downloader::Stop");
417     MEDIA_LOG_I("Stop Begin");
418     isDestructor_ = true;
419     if (requestQue_ != nullptr) {
420         requestQue_->SetActive(false);
421     }
422     if (currentRequest_ != nullptr) {
423         currentRequest_->isInterruptNeeded_ = true;
424         currentRequest_->Close();
425     }
426     if (client_ != nullptr) {
427         client_->Close(isAsync);
428         if (!isAsync) {
429             client_->Deinit();
430         }
431     }
432     shouldStartNextRequest = true;
433     if (task_ != nullptr) {
434         if (isAsync) {
435             task_->StopAsync();
436         } else {
437             task_->Stop();
438         }
439     }
440     MEDIA_LOG_I("Stop End");
441 }
442 
Seek(int64_t offset)443 bool Downloader::Seek(int64_t offset)
444 {
445     MediaAVCodec::AVCodecTrace trace("Downloader::Seek, offset: " + std::to_string(offset));
446     FALSE_RETURN_V_MSG(!isDestructor_ && !isInterruptNeeded_, false, "Seek fail, is Destructor or InterruptNeeded");
447     AutoLock lock(operatorMutex_);
448     FALSE_RETURN_V_MSG(currentRequest_ != nullptr, false, "Seek fail, currentRequest nullptr");
449     size_t contentLength = currentRequest_->GetFileContentLength();
450     MEDIA_LOG_I("Seek Begin, offset = " PUBLIC_LOG_D64 ", contentLength = " PUBLIC_LOG_ZU, offset, contentLength);
451     if (offset >= 0 && offset < static_cast<int64_t>(contentLength)) {
452         currentRequest_->startPos_ = offset;
453     }
454     size_t temp = currentRequest_->GetFileContentLength() - static_cast<size_t>(currentRequest_->startPos_);
455     currentRequest_->requestSize_ = static_cast<int>(std::min(temp, static_cast<size_t>(PER_REQUEST_SIZE)));
456     if (downloadRequestSize_ > 0) {
457         currentRequest_->requestSize_ = std::min(currentRequest_->requestSize_,
458             static_cast<int>(downloadRequestSize_));
459         downloadRequestSize_ = 0;
460     }
461     currentRequest_->isEos_ = false;
462     shouldStartNextRequest = false; // Reuse last request when seek
463     if (currentRequest_->retryTimes_ > 0) {
464         currentRequest_->retryTimes_ = 0;
465     }
466     return true;
467 }
468 
SetRequestSize(size_t downloadRequestSize)469 void Downloader::SetRequestSize(size_t downloadRequestSize)
470 {
471     downloadRequestSize_ = downloadRequestSize;
472 }
473 
GetIp(std::string & ip)474 void Downloader::GetIp(std::string &ip)
475 {
476     if (client_ != nullptr) {
477         client_->GetIp(ip);
478     }
479 }
480 
481 // Pause download thread before use currentRequest_
Retry(const std::shared_ptr<DownloadRequest> & request)482 bool Downloader::Retry(const std::shared_ptr<DownloadRequest>& request)
483 {
484     FALSE_RETURN_V_MSG(client_ != nullptr && !isDestructor_ && !isInterruptNeeded_, false,
485         "not Retry, client null or isDestructor or isInterruptNeeded");
486     if (isAppBackground_) {
487         Pause(true);
488         MEDIA_LOG_I("Retry avoid, forground to background.");
489         return true;
490     }
491     {
492         AutoLock lock(operatorMutex_);
493         MEDIA_LOG_I("0x%{public}06" PRIXPTR " Retry Begin", FAKE_POINTER(this));
494         FALSE_RETURN_V(client_ != nullptr && !shouldStartNextRequest && !isDestructor_ && !isInterruptNeeded_, false);
495         requestQue_->SetActive(false, false);
496     }
497     PauseLoop(true);
498     WaitLoopPause();
499     {
500         AutoLock lock(operatorMutex_);
501         FALSE_RETURN_V(client_ != nullptr && !shouldStartNextRequest && !isDestructor_ && !isInterruptNeeded_, false);
502         client_->Close(false);
503         if (currentRequest_ != nullptr) {
504             if (currentRequest_->IsSame(request) && !shouldStartNextRequest) {
505                 currentRequest_->retryTimes_++;
506                 currentRequest_->retryOnGoing_ = true;
507                 currentRequest_->dropedDataLen_ = 0;
508             }
509             client_->Open(currentRequest_->url_, currentRequest_->httpHeader_, currentRequest_->requestInfo_.timeoutMs);
510             requestQue_->SetActive(true);
511             currentRequest_->isEos_ = false;
512             if (currentRequest_->endPos_ > 0 && currentRequest_->startPos_ >= 0 &&
513                 currentRequest_->endPos_ >= currentRequest_->startPos_) {
514                 currentRequest_->requestSize_ = currentRequest_->endPos_ - currentRequest_->startPos_ + 1;
515             }
516         }
517     }
518     task_->Start();
519     MEDIA_LOG_I("Do retry.");
520     return true;
521 }
522 
GetSystemParam(const std::string & key)523 std::string GetSystemParam(const std::string &key)
524 {
525     char value[MAX_LEN] = {0};
526     int32_t ret = GetParameter(key.c_str(), "", value, MAX_LEN);
527     if (ret < 0) {
528         return "";
529     }
530     return std::string(value);
531 }
532 
GetUserAgent()533 std::string GetUserAgent()
534 {
535     std::string displayVersion = GetSystemParam(DISPLAYVERSION);
536     std::string userAgent = " AVPlayerLib " + displayVersion;
537     return userAgent;
538 }
539 
BeginDownload()540 bool Downloader::BeginDownload()
541 {
542     MEDIA_LOG_I("BeginDownload");
543     std::string url = currentRequest_->url_;
544     std::map<std::string, std::string> httpHeader = currentRequest_->httpHeader_;
545 
546     if (currentRequest_->httpHeader_.count(USER_AGENT) <= 0) {
547         currentRequest_->httpHeader_[USER_AGENT] = GetUserAgent();
548         httpHeader[USER_AGENT] = GetUserAgent();
549         MEDIA_LOG_I("Set default UA.");
550     }
551 
552     int32_t timeoutMs = currentRequest_->requestInfo_.timeoutMs;
553     FALSE_RETURN_V(!url.empty(), false);
554     if (client_) {
555         client_->Open(url, httpHeader, timeoutMs);
556     }
557 
558     if (currentRequest_->endPos_ <= 0) {
559         currentRequest_->startPos_ = 0;
560         currentRequest_->requestSize_ = FIRST_REQUEST_SIZE;
561     } else {
562         int64_t temp = currentRequest_->endPos_ - currentRequest_->startPos_ + 1;
563         currentRequest_->requestSize_ = static_cast<int>(std::min(temp, static_cast<int64_t>(PER_REQUEST_SIZE)));
564     }
565     currentRequest_->isEos_ = false;
566     currentRequest_->retryTimes_ = 0;
567     currentRequest_->downloadStartTime_ = currentRequest_->GetNowTime();
568     MEDIA_LOG_I("End");
569     return true;
570 }
571 
HttpDownloadLoop()572 void Downloader::HttpDownloadLoop()
573 {
574     AutoLock lock(operatorMutex_);
575     MEDIA_LOGI_LIMIT(LOOP_LOG_FEQUENCE, "Downloader loop shouldStartNextRequest %{public}d",
576         shouldStartNextRequest.load());
577     if (shouldStartNextRequest) {
578         std::shared_ptr<DownloadRequest> tempRequest = requestQue_->Pop(1000); // 1000ms timeout limit.
579         if (!tempRequest) {
580             MEDIA_LOG_W("HttpDownloadLoop tempRequest is null.");
581             noTaskLoopTimes_++;
582             if (noTaskLoopTimes_ >= LOOP_TIMES) {
583                 PauseLoop(true);
584             }
585             return;
586         }
587         noTaskLoopTimes_ = 0;
588         currentRequest_ = tempRequest;
589         if (isInterruptNeeded_) {
590             currentRequest_->isInterruptNeeded_ = true;
591         }
592         BeginDownload();
593         shouldStartNextRequest = currentRequest_->IsClosed();
594     }
595     if (currentRequest_ == nullptr || client_ == nullptr) {
596         MEDIA_LOG_I("currentRequest_ %{public}d client_ %{public}d nullptr",
597                     currentRequest_ != nullptr, client_ != nullptr);
598         PauseLoop(true);
599         return;
600     }
601     RequestData();
602     return;
603 }
604 
OpenAppUri()605 void Downloader::OpenAppUri()
606 {
607     {
608         AutoLock lock(closeMutex_);
609         appPreviousRequestUrl_ = currentRequest_->GetUrl();
610         if (sourceLoader_ != nullptr && currentRequest_ != nullptr) {
611             if (uuid_ != 0) {
612                 sourceLoader_->Close(uuid_);
613                 MEDIA_LOG_D("0x%{public}06" PRIXPTR "LoaderCombinations Close uuid " PUBLIC_LOG_D64,
614                     FAKE_POINTER(this), uuid_);
615             }
616 
617             int64_t uuid = 0;
618             for (int i = 0; i < APP_OPEN_RETRY_TIMES; i++) {
619                 uuid = sourceLoader_->Open(appPreviousRequestUrl_, currentRequest_->GetHttpHeader(), client_);
620                 if (uuid > 0) {
621                     break;
622                 }
623                 MEDIA_LOG_D("0x%{public}06" PRIXPTR "Open retry " PUBLIC_LOG_D64 " retryTimes: " PUBLIC_LOG_D32,
624                 FAKE_POINTER(this), uuid, i);
625             }
626             MEDIA_LOG_I("0x%{public}06" PRIXPTR "LoaderCombinations Open uuid " PUBLIC_LOG_D64,
627                 FAKE_POINTER(this), uuid);
628             if (uuid != 0) {
629                 client_->SetUuid(uuid);
630                 uuid_ = uuid;
631             } else {
632                 MEDIA_LOG_E("0x%{public}06" PRIXPTR "Open faild, uuid " PUBLIC_LOG_D64,
633                 FAKE_POINTER(this), uuid);
634                 std::shared_ptr<Downloader> unused;
635                 currentRequest_->statusCallback_(DownloadStatus::PARTTAL_DOWNLOAD, unused, currentRequest_);
636             }
637         }
638     }
639 }
640 
RequestData()641 void Downloader::RequestData()
642 {
643     MediaAVCodec::AVCodecTrace trace("Downloader::HttpDownloadLoop, startPos: "
644         + std::to_string(currentRequest_->startPos_) + ", reqSize: " + std::to_string(currentRequest_->requestSize_));
645     int64_t startPos = currentRequest_->startPos_;
646     if (currentRequest_->requestWholeFile_ && currentRequest_->shouldSaveData_) {
647         startPos = -1;
648     }
649     RequestInfo sourceInfo;
650     sourceInfo.url = currentRequest_->url_;
651     sourceInfo.httpHeader = currentRequest_->httpHeader_;
652     sourceInfo.timeoutMs = currentRequest_->requestInfo_.timeoutMs;
653 
654     if ((currentRequest_->protocolType_ == RequestProtocolType::HTTP && uuid_ == 0) ||
655         currentRequest_->protocolType_ == RequestProtocolType::HLS ||
656         currentRequest_->protocolType_ == RequestProtocolType::DASH) {
657         OpenAppUri();
658     }
659 
660     auto handleResponseCb = [this](int32_t clientCode, int32_t serverCode, Status ret) {
661         currentRequest_->clientError_ = clientCode;
662         currentRequest_->serverError_ = serverCode;
663         if (isDestructor_) {
664             return;
665         }
666         if (currentRequest_->requestSize_ == FIRST_REQUEST_SIZE && !currentRequest_->isFirstRangeRequestReady_
667             && currentRequest_->serverError_ == SERVER_RANGE_ERROR_CODE) {
668             MEDIA_LOG_I("first request is above filesize, need retry.");
669             currentRequest_->startPos_ = 0;
670             currentRequest_->requestSize_ = MIN_REQUEST_SIZE;
671             currentRequest_->isHeaderUpdated_ = false;
672             currentRequest_->isFirstRangeRequestReady_ = true;
673             currentRequest_->headerInfo_.fileContentLen = 0;
674             return;
675         }
676         if (ret == Status::OK) {
677             HandleRetOK();
678         } else {
679             PauseLoop(true);
680             MEDIA_LOG_E("Client request data failed. ret = " PUBLIC_LOG_D32 ", clientCode = " PUBLIC_LOG_D32
681                 ",request queue size: " PUBLIC_LOG_U64, static_cast<int32_t>(ret),
682                 static_cast<int32_t>(clientCode), static_cast<int64_t>(requestQue_->Size()));
683             HandleRetErrorCode();
684             std::shared_ptr<Downloader> unused;
685             currentRequest_->statusCallback_(DownloadStatus::PARTTAL_DOWNLOAD, unused, currentRequest_);
686         }
687     };
688     MEDIA_LOG_I("0x%{public}06" PRIXPTR " RequestData enter.", FAKE_POINTER(this));
689     client_->RequestData(startPos, currentRequest_->requestSize_, sourceInfo, handleResponseCb);
690     MEDIA_LOG_I("0x%{public}06" PRIXPTR " RequestData end.", FAKE_POINTER(this));
691 }
692 
HandleRetErrorCode()693 void Downloader::HandleRetErrorCode()
694 {
695     if (currentRequest_ && currentRequest_->serverError_ == REQUEST_OFTEN_ERROR_CODE) {
696         int sleepTime = 0;
697         while (!isInterruptNeeded_ && sleepTime <= 1000) { // 1000:sleep 1s
698             Task::SleepInTask(SLEEP_TEN_MICRO_SEC);
699             sleepTime += SLEEP_TEN_MICRO_SEC;
700         }
701     }
702 }
HandlePlayingFinish()703 void Downloader::HandlePlayingFinish()
704 {
705     if (requestQue_->Empty()) {
706         PauseLoop(true);
707     }
708     shouldStartNextRequest = true;
709     if (currentRequest_->downloadDoneCallback_ && !isDestructor_) {
710         currentRequest_->downloadDoneTime_ = currentRequest_->GetNowTime();
711         currentRequest_->downloadDoneCallback_(currentRequest_->GetUrl(), currentRequest_->location_);
712         currentRequest_->isFirstRangeRequestReady_ = false;
713     }
714 }
715 
HandleRetOK()716 void Downloader::HandleRetOK()
717 {
718     if (currentRequest_->retryTimes_ > 0) {
719         currentRequest_->retryTimes_ = 0;
720     }
721     if (currentRequest_->headerInfo_.isChunked && requestQue_->Empty()) {
722         currentRequest_->isEos_ = true;
723         PauseLoop(true);
724         return;
725     }
726 
727     int64_t remaining = 0;
728     if (currentRequest_->endPos_ <= 0) {
729         remaining = static_cast<int64_t>(currentRequest_->headerInfo_.fileContentLen) -
730                     currentRequest_->startPos_;
731     } else {
732         remaining = currentRequest_->endPos_ - currentRequest_->startPos_ + 1;
733     }
734     if (currentRequest_->headerInfo_.fileContentLen > 0 && remaining <= 0) { // Check whether the playback ends.
735         MEDIA_LOG_I("http transfer reach end, startPos_ " PUBLIC_LOG_D64, currentRequest_->startPos_);
736         currentRequest_->isEos_ = true;
737         HandlePlayingFinish();
738         return;
739     }
740     if (currentRequest_->headerInfo_.fileContentLen == 0 && remaining <= 0) {
741         currentRequest_->isEos_ = true;
742         currentRequest_->Close();
743         HandlePlayingFinish();
744         return;
745     }
746     if (remaining < PER_REQUEST_SIZE) {
747         currentRequest_->requestSize_ = remaining;
748     } else {
749         currentRequest_->requestSize_ = PER_REQUEST_SIZE;
750     }
751 }
752 
UpdateHeaderInfo(Downloader * mediaDownloader)753 void Downloader::UpdateHeaderInfo(Downloader* mediaDownloader)
754 {
755     if (mediaDownloader->currentRequest_->isHeaderUpdated_) {
756         return;
757     }
758     MEDIA_LOG_I("UpdateHeaderInfo enter.");
759     HeaderInfo* info = &(mediaDownloader->currentRequest_->headerInfo_);
760     if (info->contentLen > 0 && info->contentLen < LIVE_CONTENT_LENGTH) {
761         info->isChunked = false;
762     }
763     if (info->contentLen <= 0 && !mediaDownloader->currentRequest_->IsM3u8Request()) {
764         info->isChunked = true;
765     }
766     if (info->fileContentLen > 0 && info->isChunked && !mediaDownloader->currentRequest_->IsM3u8Request()) {
767         info->isChunked = false;
768     }
769     mediaDownloader->currentRequest_->SaveHeader(info);
770 }
771 
IsDropDataRetryRequest(Downloader * mediaDownloader)772 bool Downloader::IsDropDataRetryRequest(Downloader* mediaDownloader)
773 {
774     bool isWholeFileRetry = mediaDownloader->currentRequest_->requestWholeFile_ &&
775                             mediaDownloader->currentRequest_->shouldSaveData_ &&
776                             mediaDownloader->currentRequest_->retryOnGoing_;
777     if (!isWholeFileRetry) {
778         return false;
779     }
780     if (mediaDownloader->currentRequest_->startPos_ > 0) {
781         return true;
782     } else {
783         mediaDownloader->currentRequest_->retryOnGoing_ = false;
784         return false;
785     }
786 }
787 
DropRetryData(void * buffer,size_t dataLen,Downloader * mediaDownloader)788 size_t Downloader::DropRetryData(void* buffer, size_t dataLen, Downloader* mediaDownloader)
789 {
790     auto currentRequest_ = mediaDownloader->currentRequest_;
791     int64_t writeOffSet = -1;
792     if (currentRequest_->startPos_ > 0) {
793         writeOffSet = currentRequest_->startPos_ >= static_cast<int64_t>(dataLen) ?
794             0 : currentRequest_->startPos_; // 0:drop all
795     }
796     bool dropRet = false;
797     uint32_t writeLen = 0;
798     if (writeOffSet > 0) {
799         int64_t secondParam = static_cast<int64_t>(dataLen) - writeOffSet;
800         if (secondParam < 0) {
801             secondParam = 0;
802         }
803         writeLen = currentRequest_->saveData_(static_cast<uint8_t *>(buffer) + writeOffSet,
804             static_cast<uint32_t>(secondParam), mediaDownloader->isNotBlock_);
805         dropRet = writeLen == secondParam;
806         currentRequest_->dropedDataLen_ = currentRequest_->dropedDataLen_ + writeOffSet;
807         MEDIA_LOG_D("DropRetryData: last drop, droped len " PUBLIC_LOG_D64 ", startPos_ " PUBLIC_LOG_D64,
808                     currentRequest_->dropedDataLen_, currentRequest_->startPos_);
809     } else if (writeOffSet == 0) {
810         currentRequest_->dropedDataLen_ += static_cast<int64_t>(dataLen);
811         dropRet = true;
812         MEDIA_LOG_D("DropRetryData: drop, droped len " PUBLIC_LOG_D64 ", startPos_ " PUBLIC_LOG_D64,
813                     currentRequest_->dropedDataLen_, currentRequest_->startPos_);
814     } else {
815         MEDIA_LOG_E("drop data error");
816     }
817     if (dropRet && currentRequest_->startPos_ == currentRequest_->dropedDataLen_) {
818         currentRequest_->retryOnGoing_ = false;
819         currentRequest_->dropedDataLen_ = 0;
820         if (writeOffSet > 0) {
821             currentRequest_->startPos_ += static_cast<int64_t>(dataLen) - writeOffSet;
822         }
823         MEDIA_LOG_I("drop data finished, startPos_ " PUBLIC_LOG_D64, currentRequest_->startPos_);
824     }
825     if (!dropRet && mediaDownloader->sourceLoader_ != nullptr) {
826         mediaDownloader->currentRequest_->startPos_ += static_cast<int64_t>(writeLen);
827         mediaDownloader->PauseLoop(true);
828         mediaDownloader->currentRequest_->retryOnGoing_ = true;
829         mediaDownloader->currentRequest_->dropedDataLen_ = 0;
830     }
831     return dropRet ? dataLen : 0; // 0:save data failed or drop error
832 }
833 
UpdateCurRequest(Downloader * mediaDownloader,HeaderInfo * header)834 void Downloader::UpdateCurRequest(Downloader* mediaDownloader, HeaderInfo* header)
835 {
836     int64_t hstTime = 0;
837     Sec2HstTime(mediaDownloader->currentRequest_->GetDuration(), hstTime);
838     int64_t startTimePos = mediaDownloader->currentRequest_->startTimePos_;
839     int64_t contenLen = static_cast<int64_t>(header->fileContentLen);
840     int64_t startPos = 0;
841     if (hstTime != 0) {
842         startPos = contenLen * startTimePos / (HstTime2Ns(hstTime));
843     }
844     mediaDownloader->currentRequest_->startPos_ = startPos;
845     mediaDownloader->currentRequest_->shouldSaveData_ = true;
846     mediaDownloader->currentRequest_->requestWholeFile_ = false;
847     mediaDownloader->currentRequest_->requestSize_ = PER_REQUEST_SIZE;
848     mediaDownloader->currentRequest_->startTimePos_ = 0;
849 }
850 
HandleFileContentLen(HeaderInfo * header)851 void Downloader::HandleFileContentLen(HeaderInfo* header)
852 {
853     if (header->fileContentLen == 0) {
854         if (header->contentLen > 0) {
855             MEDIA_LOG_W("Unsupported range, use content length as content file length, contentLen: " PUBLIC_LOG_D32,
856                 static_cast<int32_t>(header->contentLen));
857             header->fileContentLen = static_cast<size_t>(header->contentLen);
858         } else {
859             MEDIA_LOG_D("fileContentLen and contentLen are both zero.");
860         }
861     }
862 }
863 
RxBodyData(void * buffer,size_t size,size_t nitems,void * userParam)864 size_t Downloader::RxBodyData(void* buffer, size_t size, size_t nitems, void* userParam)
865 {
866     auto mediaDownloader = static_cast<Downloader *>(userParam);
867     size_t dataLen = size * nitems;
868     int64_t curLen = mediaDownloader->currentRequest_->realRecvContentLen_;
869     int64_t realRecvContentLen = static_cast<int64_t>(dataLen) + curLen;
870     UpdateHeaderInfo(mediaDownloader);
871     MediaAVCodec::AVCodecTrace trace("Downloader::RxBodyData, dataLen: " + std::to_string(dataLen)
872         + ", realRecvContentLen: " + std::to_string(realRecvContentLen));
873     mediaDownloader->currentRequest_->realRecvContentLen_ = realRecvContentLen;
874 
875     if (IsDropDataRetryRequest(mediaDownloader) && !mediaDownloader->currentRequest_->IsIndexM3u8Request()) {
876         return DropRetryData(buffer, dataLen, mediaDownloader);
877     }
878     HeaderInfo* header = &(mediaDownloader->currentRequest_->headerInfo_);
879     if (!mediaDownloader->currentRequest_->shouldSaveData_) {
880         UpdateCurRequest(mediaDownloader, header);
881         return dataLen;
882     }
883     HandleFileContentLen(header);
884     if (!mediaDownloader->currentRequest_->isDownloading_) {
885         mediaDownloader->currentRequest_->isDownloading_ = true;
886     }
887     uint32_t writeLen = mediaDownloader->currentRequest_->saveData_(static_cast<uint8_t *>(buffer),
888         static_cast<uint32_t>(dataLen), mediaDownloader->isNotBlock_);
889     MEDIA_LOGI_LIMIT(DOWNLOAD_LOG_FEQUENCE, "RxBodyData: dataLen " PUBLIC_LOG_ZU ", startPos_ " PUBLIC_LOG_D64, dataLen,
890                      mediaDownloader->currentRequest_->startPos_);
891     mediaDownloader->currentRequest_->startPos_ = mediaDownloader->currentRequest_->startPos_ +
892         static_cast<int64_t>(writeLen);
893 
894     int64_t remaining = 0;
895     if (mediaDownloader->currentRequest_->endPos_ <= 0) {
896         remaining = static_cast<int64_t>(mediaDownloader->currentRequest_->headerInfo_.fileContentLen) -
897                     mediaDownloader->currentRequest_->startPos_;
898     } else {
899         remaining = mediaDownloader->currentRequest_->endPos_ - mediaDownloader->currentRequest_->startPos_ + 1;
900     }
901 
902     mediaDownloader->currentRequest_->requestSize_ = remaining < PER_REQUEST_SIZE ? remaining : PER_REQUEST_SIZE;
903 
904     if (writeLen != dataLen) {
905         if (mediaDownloader->sourceLoader_ != nullptr) {
906             mediaDownloader->PauseLoop(true);
907             mediaDownloader->currentRequest_->retryOnGoing_ = true;
908             mediaDownloader->currentRequest_->dropedDataLen_ = 0;
909         }
910         MEDIA_LOG_W("Save data failed.");
911         return 0; // save data failed, make perform finished.
912     }
913 
914     mediaDownloader->currentRequest_->isDownloading_ = false;
915     return dataLen;
916 }
917 
918 namespace {
StringTrim(char * str)919 char* StringTrim(char* str)
920 {
921     if (str == nullptr) {
922         return nullptr;
923     }
924     char* p = str;
925     char* p1 = p + strlen(str) - 1;
926 
927     while (*p && isspace(static_cast<int>(*p))) {
928         p++;
929     }
930     while (p1 > p && isspace(static_cast<int>(*p1))) {
931         *p1-- = 0;
932     }
933     return p;
934 }
935 }
936 
HandleContentRange(HeaderInfo * info,char * key,char * next,size_t size,size_t nitems)937 bool Downloader::HandleContentRange(HeaderInfo* info, char* key, char* next, size_t size, size_t nitems)
938 {
939     if (!strncmp(key, "Content-Range", strlen("Content-Range")) ||
940         !strncmp(key, "content-range", strlen("content-range"))) {
941         char* token = strtok_s(nullptr, ":", &next);
942         FALSE_RETURN_V(token != nullptr, false);
943         char* strRange = StringTrim(token);
944         size_t start;
945         size_t end;
946         size_t fileLen;
947         FALSE_LOG_MSG(sscanf_s(strRange, "bytes %lu-%lu/%lu", &start, &end, &fileLen) != -1,
948             "sscanf get range failed");
949         if (info->fileContentLen > 0 && info->fileContentLen != fileLen) {
950             MEDIA_LOG_E("FileContentLen doesn't equal to fileLen");
951         }
952         if (info->fileContentLen == 0) {
953             info->fileContentLen = fileLen;
954         }
955     }
956     return true;
957 }
958 
HandleContentType(HeaderInfo * info,char * key,char * next,size_t headerSize,Downloader * mediaDownloader)959 bool Downloader::HandleContentType(HeaderInfo* info, char* key, char* next, size_t headerSize,
960                                    Downloader* mediaDownloader)
961 {
962     if (!strncmp(key, "Content-Type", strlen("Content-Type"))) {
963         char* token = strtok_s(nullptr, ":", &next);
964         FALSE_RETURN_V(token != nullptr, false);
965         char* type = StringTrim(token);
966         std::string tokenStr = (std::string)token;
967         MEDIA_LOG_I("Content-Type: " PUBLIC_LOG_S, tokenStr.c_str());
968         NZERO_LOG(memcpy_s(info->contentType, sizeof(info->contentType), type, strlen(type)));
969     }
970     return true;
971 }
972 
HandleContentEncode(HeaderInfo * info,char * key,char * next,size_t size,size_t nitems)973 bool Downloader::HandleContentEncode(HeaderInfo* info, char* key, char* next, size_t size, size_t nitems)
974 {
975     if (!strncmp(key, "Content-Encode", strlen("Content-Encode")) ||
976         !strncmp(key, "content-encode", strlen("content-encode"))) {
977         char* token = strtok_s(nullptr, ":", &next);
978         FALSE_RETURN_V(token != nullptr, false);
979         std::string tokenStr = (std::string)token;
980         MEDIA_LOG_I("Content-Encode: " PUBLIC_LOG_S, tokenStr.c_str());
981     }
982     return true;
983 }
984 
HandleContentLength(HeaderInfo * info,char * key,char * next,Downloader * mediaDownloader)985 bool Downloader::HandleContentLength(HeaderInfo* info, char* key, char* next, Downloader* mediaDownloader)
986 {
987     FALSE_RETURN_V(key != nullptr, false);
988     if (!strncmp(key, "Content-Length", strlen("Content-Length")) ||
989         !strncmp(key, "content-length", strlen("content-length"))) {
990         FALSE_RETURN_V(next != nullptr, false);
991         char* token = strtok_s(nullptr, ":", &next);
992         FALSE_RETURN_V(token != nullptr, false);
993         if (info != nullptr && mediaDownloader != nullptr) {
994             info->contentLen = atol(StringTrim(token));
995             if (info->contentLen <= 0 && !mediaDownloader->currentRequest_->IsM3u8Request()) {
996                 info->isChunked = true;
997             }
998         }
999     }
1000     return true;
1001 }
1002 
1003 // Check if this server supports range download. (HTTP)
HandleRange(HeaderInfo * info,char * key,char * next,size_t size,size_t nitems)1004 bool Downloader::HandleRange(HeaderInfo* info, char* key, char* next, size_t size, size_t nitems)
1005 {
1006     if (!strncmp(key, "Accept-Ranges", strlen("Accept-Ranges")) ||
1007         !strncmp(key, "accept-ranges", strlen("accept-ranges"))) {
1008         char* token = strtok_s(nullptr, ":", &next);
1009         FALSE_RETURN_V(token != nullptr, false);
1010         if (!strncmp(StringTrim(token), "bytes", strlen("bytes"))) {
1011             info->isServerAcceptRange = true;
1012             MEDIA_LOG_I("Accept-Ranges: bytes");
1013         }
1014     }
1015     if (!strncmp(key, "Content-Range", strlen("Content-Range")) ||
1016         !strncmp(key, "content-range", strlen("content-range"))) {
1017         char* token = strtok_s(nullptr, ":", &next);
1018         FALSE_RETURN_V(token != nullptr, false);
1019         std::string tokenStr = (std::string)token;
1020         if (tokenStr.find("bytes") != std::string::npos) {
1021             info->isServerAcceptRange = true;
1022             MEDIA_LOG_I("Content-Range: " PUBLIC_LOG_S, tokenStr.c_str());
1023         }
1024     }
1025     return true;
1026 }
1027 
RxHeaderData(void * buffer,size_t size,size_t nitems,void * userParam)1028 size_t Downloader::RxHeaderData(void* buffer, size_t size, size_t nitems, void* userParam)
1029 {
1030     MediaAVCodec::AVCodecTrace trace("Downloader::RxHeaderData");
1031     auto mediaDownloader = static_cast<Downloader *>(userParam);
1032     HeaderInfo* info = &(mediaDownloader->currentRequest_->headerInfo_);
1033     if (mediaDownloader->currentRequest_->isHeaderUpdated_) {
1034         return size * nitems;
1035     }
1036     char* next = nullptr;
1037     char* key = strtok_s(reinterpret_cast<char*>(buffer), ":", &next);
1038     FALSE_RETURN_V(key != nullptr, size * nitems);
1039 
1040     if (!strncmp(key, "Transfer-Encoding", strlen("Transfer-Encoding")) ||
1041         !strncmp(key, "transfer-encoding", strlen("transfer-encoding"))) {
1042         char* token = strtok_s(nullptr, ":", &next);
1043         FALSE_RETURN_V(token != nullptr, size * nitems);
1044         if (!strncmp(StringTrim(token), "chunked", strlen("chunked")) &&
1045             !mediaDownloader->currentRequest_->IsM3u8Request()) {
1046             info->isChunked = true;
1047             if (static_cast<int32_t>(mediaDownloader->currentRequest_->url_.find(".flv") == std::string::npos)) {
1048                 info->contentLen = LIVE_CONTENT_LENGTH;
1049             } else {
1050                 info->contentLen = 0;
1051             }
1052             std::string tokenStr = (std::string)token;
1053             MEDIA_LOG_I("Transfer-Encoding: " PUBLIC_LOG_S, tokenStr.c_str());
1054         }
1055     }
1056     if (!strncmp(key, "Location", strlen("Location")) ||
1057         !strncmp(key, "location", strlen("location"))) {
1058         FALSE_RETURN_V(next != nullptr, size * nitems);
1059         char* location = StringTrim(next);
1060         mediaDownloader->currentRequest_->location_ = location;
1061     }
1062 
1063     if (!HandleContentRange(info, key, next, size, nitems) ||
1064         !HandleContentType(info, key, next, size * nitems, mediaDownloader) ||
1065         !HandleContentEncode(info, key, next, size, nitems) ||
1066         !HandleContentLength(info, key, next, mediaDownloader) ||
1067         !HandleRange(info, key, next, size, nitems)) {
1068         return size * nitems;
1069     }
1070 
1071     return size * nitems;
1072 }
1073 
PauseLoop(bool isAsync)1074 void Downloader::PauseLoop(bool isAsync)
1075 {
1076     if (task_ == nullptr) {
1077         return;
1078     }
1079     if (isAsync) {
1080         task_->PauseAsync();
1081     } else {
1082         task_->Pause();
1083     }
1084 }
1085 
SetAppUid(int32_t appUid)1086 void Downloader::SetAppUid(int32_t appUid)
1087 {
1088     if (client_) {
1089         client_->SetAppUid(appUid);
1090     }
1091 }
1092 
GetCurrentRequest()1093 const std::shared_ptr<DownloadRequest>& Downloader::GetCurrentRequest()
1094 {
1095     return currentRequest_;
1096 }
1097 
SetInterruptState(bool isInterruptNeeded)1098 void Downloader::SetInterruptState(bool isInterruptNeeded)
1099 {
1100     MEDIA_LOG_I("0x%{public}06" PRIXPTR " Downloader SetInterruptState %{public}d",
1101         FAKE_POINTER(this), isInterruptNeeded);
1102     isInterruptNeeded_ = isInterruptNeeded;
1103     if (currentRequest_ != nullptr) {
1104         currentRequest_->isInterruptNeeded_ = isInterruptNeeded;
1105     }
1106     if (sourceLoader_ != nullptr) {
1107         client_->Close(false);
1108     }
1109     NotifyLoopPause();
1110 }
1111 
NotifyLoopPause()1112 void Downloader::NotifyLoopPause()
1113 {
1114     AutoLock lk(loopPauseMutex_);
1115     if (loopStatus_ == LoopStatus::PAUSE || isInterruptNeeded_) {
1116         MEDIA_LOG_I("0x%{public}06" PRIXPTR " Downloader NotifyLoopPause", FAKE_POINTER(this));
1117         loopStatus_ = LoopStatus::IDLE;
1118         loopPauseCond_.NotifyAll();
1119     } else {
1120         loopStatus_ = LoopStatus::IDLE;
1121         MEDIA_LOG_I("Downloader not NotifyLoopPause loopStatus %{public}d isInterruptNeeded %{public}d",
1122             loopStatus_.load(), isInterruptNeeded_.load());
1123     }
1124 }
1125 
WaitLoopPause()1126 void Downloader::WaitLoopPause()
1127 {
1128     AutoLock lk(loopPauseMutex_);
1129     if (loopStatus_ == LoopStatus::IDLE) {
1130         MEDIA_LOG_I("0x%{public}06" PRIXPTR "Downloader not WaitLoopPause loopStatus is idle", FAKE_POINTER(this));
1131         return;
1132     }
1133     MEDIA_LOG_I("0x%{public}06" PRIXPTR "Downloader WaitLoopPause task loopStatus_ %{public}d",
1134         FAKE_POINTER(this), loopStatus_.load());
1135     loopStatus_ = LoopStatus::PAUSE;
1136     loopPauseCond_.Wait(lk, [this]() {
1137         MEDIA_LOG_I("0x%{public}06" PRIXPTR " WaitLoopPause wake loopStatus %{public}d",
1138             FAKE_POINTER(this), loopStatus_.load());
1139         return loopStatus_ != LoopStatus::PAUSE || isInterruptNeeded_;
1140     });
1141 }
1142 
SetAppState(bool isAppBackground)1143 void Downloader::SetAppState(bool isAppBackground)
1144 {
1145     isAppBackground_ = isAppBackground;
1146 }
1147 
StopBufferring()1148 void Downloader::StopBufferring()
1149 {
1150     MediaAVCodec::AVCodecTrace trace("Downloader::StopBufferring");
1151     if (task_ == nullptr || currentRequest_ == nullptr) {
1152         MEDIA_LOG_E("Downloader StopBufferring error.");
1153         return;
1154     }
1155     if (isAppBackground_) {
1156         if (!task_->IsTaskRunning() && client_ != nullptr) {
1157             MEDIA_LOG_I("StopBufferring: is task not running.");
1158             client_->Close(false);
1159         }
1160     } else {
1161         if (currentRequest_ != nullptr && !shouldStartNextRequest) {
1162             int64_t lastStartPos = currentRequest_->startPos_; // downlaod from last pos
1163             BeginDownload();
1164             currentRequest_->startPos_ = lastStartPos;
1165             if (currentRequest_->startPos_ > 0) {
1166                 currentRequest_->retryOnGoing_ = true;
1167                 currentRequest_->dropedDataLen_ = 0;
1168             }
1169             MEDIA_LOG_I("StopBufferring: begin pos " PUBLIC_LOG_U64, currentRequest_->startPos_);
1170         }
1171         Start();
1172     }
1173 }
1174 }
1175 }
1176 }
1177 }
1178