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 #define HST_LOG_TAG "DownloadMonitor"
16
17 #include "monitor/download_monitor.h"
18 #include "cpp_ext/algorithm_ext.h"
19
20 namespace OHOS {
21 namespace Media {
22 namespace Plugins {
23 namespace HttpPlugin {
24 namespace {
25 constexpr int RETRY_TIMES_TO_REPORT_ERROR = 10;
26 constexpr int APP_DOWNLOAD_RETRY_TIMES = 60;
27 constexpr int SERVER_ERROR_THRESHOLD = 500;
28 constexpr int32_t READ_LOG_FEQUENCE = 50;
29 constexpr int64_t MICROSECONDS_TO_MILLISECOND = 1000;
30 constexpr int64_t RETRY_SEG = 50;
31 constexpr int32_t REDIRECT_CODE = 302;
32 const std::set<int32_t> CLIENT_NOT_RETRY_ERROR_CODES = {
33 992,
34 };
35 const std::set<int32_t> CLIENT_RETRY_ERROR_CODES = {
36 -1, // Application resource not ready for access
37 23, // notBlock
38 25, // Upload faild.
39 26, // Faild to open/read local data from file/application.
40 28, // Timeout was reached.
41 56,
42 18,
43 0,
44 };
45 const std::set<int32_t> SERVER_RETRY_ERROR_CODES = {
46 300,
47 301,
48 302,
49 303,
50 304,
51 305,
52 403,
53 500,
54 0,
55 };
56 }
57
DownloadMonitor(std::shared_ptr<MediaDownloader> downloader)58 DownloadMonitor::DownloadMonitor(std::shared_ptr<MediaDownloader> downloader) noexcept
59 : downloader_(std::move(downloader))
60 {
61 auto statusCallback = [this] (DownloadStatus&& status, std::shared_ptr<Downloader>& downloader,
62 std::shared_ptr<DownloadRequest>& request) {
63 if (isClosed_) {
64 MEDIA_LOG_W("Downloader monitor is already closed.");
65 return;
66 }
67 OnDownloadStatus(std::forward<decltype(downloader)>(downloader), std::forward<decltype(request)>(request));
68 };
69 downloader_->SetStatusCallback(statusCallback);
70 task_ = std::make_shared<Task>(std::string("OS_HttpMonitor"));
71 task_->RegisterJob([this] { return HttpMonitorLoop(); });
72 task_->Start();
73 }
74
HttpMonitorLoop()75 int64_t DownloadMonitor::HttpMonitorLoop()
76 {
77 RetryRequest task;
78 {
79 AutoLock lock(taskMutex_);
80 if (!retryTasks_.empty()) {
81 task = retryTasks_.front();
82 retryTasks_.pop_front();
83 }
84 }
85 if (task.request && task.function) {
86 task.function();
87 }
88 return RETRY_SEG * MICROSECONDS_TO_MILLISECOND; // retry after 50ms
89 }
90
Open(const std::string & url,const std::map<std::string,std::string> & httpHeader)91 bool DownloadMonitor::Open(const std::string& url, const std::map<std::string, std::string>& httpHeader)
92 {
93 isPlaying_ = true;
94 {
95 AutoLock lock(taskMutex_);
96 retryTasks_.clear();
97 }
98 return downloader_->Open(url, httpHeader);
99 }
100
Pause()101 void DownloadMonitor::Pause()
102 {
103 if (downloader_ != nullptr) {
104 downloader_->Pause();
105 }
106 }
107
Resume()108 void DownloadMonitor::Resume()
109 {
110 if (downloader_ != nullptr) {
111 downloader_->Resume();
112 }
113 }
114
Close(bool isAsync)115 void DownloadMonitor::Close(bool isAsync)
116 {
117 isClosed_ = true;
118 {
119 AutoLock lock(taskMutex_);
120 retryTasks_.clear();
121 }
122 if (isAsync) {
123 downloader_->Close(true);
124 task_->Stop();
125 } else {
126 task_->Stop();
127 downloader_->Close(false);
128 }
129 isPlaying_ = false;
130 }
131
Read(unsigned char * buff,ReadDataInfo & readDataInfo)132 Status DownloadMonitor::Read(unsigned char* buff, ReadDataInfo& readDataInfo)
133 {
134 auto ret = downloader_->Read(buff, readDataInfo);
135 time(&lastReadTime_);
136 if (ULLONG_MAX - haveReadData_ > readDataInfo.realReadLength_) {
137 haveReadData_ += readDataInfo.realReadLength_;
138 }
139 MEDIA_LOGI_LIMIT(READ_LOG_FEQUENCE, "DownloadMonitor: haveReadData " PUBLIC_LOG_U64, haveReadData_);
140 if (readDataInfo.isEos_ && ret == Status::END_OF_STREAM) {
141 MEDIA_LOG_I("buffer is empty, read eos." PUBLIC_LOG_U64, haveReadData_);
142 }
143 return ret;
144 }
145
SeekToPos(int64_t offset,bool & isSeekHIt)146 bool DownloadMonitor::SeekToPos(int64_t offset, bool& isSeekHIt)
147 {
148 isPlaying_ = true;
149 bool isSeekHit = false;
150 bool res = downloader_->SeekToPos(offset, isSeekHit);
151 if (!isSeekHit) {
152 AutoLock lock(taskMutex_);
153 retryTasks_.clear();
154 }
155 return res;
156 }
157
GetContentLength() const158 size_t DownloadMonitor::GetContentLength() const
159 {
160 return downloader_->GetContentLength();
161 }
162
GetDuration() const163 int64_t DownloadMonitor::GetDuration() const
164 {
165 return downloader_->GetDuration();
166 }
167
GetSeekable() const168 Seekable DownloadMonitor::GetSeekable() const
169 {
170 return downloader_->GetSeekable();
171 }
172
SeekToTime(int64_t seekTime,SeekMode mode)173 bool DownloadMonitor::SeekToTime(int64_t seekTime, SeekMode mode)
174 {
175 isPlaying_ = true;
176 {
177 AutoLock lock(taskMutex_);
178 retryTasks_.clear();
179 }
180 return downloader_->SeekToTime(seekTime, mode);
181 }
182
GetBitRates()183 std::vector<uint32_t> DownloadMonitor::GetBitRates()
184 {
185 return downloader_->GetBitRates();
186 }
187
SelectBitRate(uint32_t bitRate)188 bool DownloadMonitor::SelectBitRate(uint32_t bitRate)
189 {
190 return downloader_->SelectBitRate(bitRate);
191 }
192
AutoSelectBitRate(uint32_t bitRate)193 bool DownloadMonitor::AutoSelectBitRate(uint32_t bitRate)
194 {
195 return downloader_->AutoSelectBitRate(bitRate);
196 }
197
SetCallback(Callback * cb)198 void DownloadMonitor::SetCallback(Callback* cb)
199 {
200 callback_ = cb;
201 downloader_->SetCallback(cb);
202 }
203
SetStatusCallback(StatusCallbackFunc cb)204 void DownloadMonitor::SetStatusCallback(StatusCallbackFunc cb)
205 {
206 }
207
GetStartedStatus()208 bool DownloadMonitor::GetStartedStatus()
209 {
210 return downloader_->GetStartedStatus();
211 }
212
213 // Notify client and server error.
NotifyError(int32_t clientErrorCode,int32_t serverErrorCode)214 void DownloadMonitor::NotifyError(int32_t clientErrorCode, int32_t serverErrorCode)
215 {
216 if (callback_ == nullptr) {
217 MEDIA_LOG_E("callback_ is nullptr, notify error failed.");
218 return;
219 }
220 if (clientErrorCode != 0) {
221 int32_t errorCode = MediaServiceErrCode::MSERR_DATA_SOURCE_IO_ERROR;
222 GetClientMediaServiceErrorCode(clientErrorCode, errorCode);
223 if (downloader_ != nullptr) {
224 downloader_->SetIsReportedErrorCode();
225 }
226 callback_->OnEvent({PluginEventType::SERVER_ERROR, {errorCode}, "client error"});
227 MEDIA_LOG_E("Notify http client error, code " PUBLIC_LOG_D32, clientErrorCode);
228 }
229 if (serverErrorCode != 0) {
230 int32_t errorCode = MediaServiceErrCode::MSERR_DATA_SOURCE_IO_ERROR;
231 GetServerMediaServiceErrorCode(serverErrorCode, errorCode);
232 if (downloader_ != nullptr) {
233 downloader_->SetIsReportedErrorCode();
234 }
235 callback_->OnEvent({PluginEventType::SERVER_ERROR, {errorCode}, "server error"});
236 MEDIA_LOG_E("Notify http server error, code " PUBLIC_LOG_D32, serverErrorCode);
237 }
238 }
239
NeedRetry(const std::shared_ptr<DownloadRequest> & request)240 bool DownloadMonitor::NeedRetry(const std::shared_ptr<DownloadRequest>& request)
241 {
242 auto clientError = request->GetClientError();
243 int serverError = request->GetServerError();
244 auto retryTimes = request->GetRetryTimes();
245 isNeedClearBuffer_ = serverError == REDIRECT_CODE;
246 MEDIA_LOG_I("NeedRetry: clientError = " PUBLIC_LOG_D32 ", serverError = " PUBLIC_LOG_D32
247 ", retryTimes = " PUBLIC_LOG_D32 ",", clientError, serverError, retryTimes);
248 if (CLIENT_NOT_RETRY_ERROR_CODES.find(static_cast<int32_t>(clientError)) != CLIENT_NOT_RETRY_ERROR_CODES.end()) {
249 MEDIA_LOG_I("Client error code is 23 or 992, not retry.");
250 return false;
251 }
252
253 if (downloader_ != nullptr && downloader_->IsNotRetry(request)) { // flv living
254 NotifyError(clientError, serverError);
255 downloader_->SetDownloadErrorState();
256 return false;
257 }
258
259 if (clientError == 0 && serverError == 0) {
260 return false;
261 }
262 if ((GetPlayable() && !GetReadTimeOut(clientError == -1))) { // -1: NOT_READY
263 return true;
264 }
265
266 if (CLIENT_RETRY_ERROR_CODES.find(clientError) == CLIENT_RETRY_ERROR_CODES.end() ||
267 SERVER_RETRY_ERROR_CODES.find(serverError) == SERVER_RETRY_ERROR_CODES.end() ||
268 serverError > SERVER_ERROR_THRESHOLD) {
269 MEDIA_LOG_I("error code dont't need to retry.");
270 NotifyError(clientError, serverError);
271 if (downloader_ != nullptr) {
272 downloader_->SetDownloadErrorState();
273 }
274 request->Close();
275 return false;
276 }
277
278 int retryTimesTmp = clientError == -1 ? APP_DOWNLOAD_RETRY_TIMES : RETRY_TIMES_TO_REPORT_ERROR;
279 if (retryTimes > retryTimesTmp) { // Report error to upper layer
280 MEDIA_LOG_I("Retry times readches the upper limit.");
281 NotifyError(clientError, serverError);
282 if (downloader_ != nullptr) {
283 downloader_->SetDownloadErrorState();
284 }
285 return false;
286 }
287 return true;
288 }
289
OnDownloadStatus(std::shared_ptr<Downloader> & downloader,std::shared_ptr<DownloadRequest> & request)290 void DownloadMonitor::OnDownloadStatus(std::shared_ptr<Downloader>& downloader,
291 std::shared_ptr<DownloadRequest>& request)
292 {
293 FALSE_RETURN_MSG(downloader != nullptr, "downloader is nullptr.");
294 if (NeedRetry(request)) {
295 if (isNeedClearBuffer_) {
296 downloader_->ClearBuffer();
297 }
298 AutoLock lock(taskMutex_);
299 bool exists = CppExt::AnyOf(retryTasks_.begin(), retryTasks_.end(), [&](const RetryRequest& item) {
300 return item.request->IsSame(request);
301 });
302 if (!exists) {
303 RetryRequest retryRequest {request, [downloader, request] { downloader->Retry(request); }};
304 retryTasks_.emplace_back(std::move(retryRequest));
305 }
306 }
307 }
308
SetIsTriggerAutoMode(bool isAuto)309 void DownloadMonitor::SetIsTriggerAutoMode(bool isAuto)
310 {
311 downloader_->SetIsTriggerAutoMode(isAuto);
312 }
313
SetDemuxerState(int32_t streamId)314 void DownloadMonitor::SetDemuxerState(int32_t streamId)
315 {
316 downloader_->SetDemuxerState(streamId);
317 }
318
SetReadBlockingFlag(bool isReadBlockingAllowed)319 void DownloadMonitor::SetReadBlockingFlag(bool isReadBlockingAllowed)
320 {
321 FALSE_RETURN_MSG(downloader_ != nullptr, "SetReadBlockingFlag downloader is null");
322 downloader_->SetReadBlockingFlag(isReadBlockingAllowed);
323 }
324
SetPlayStrategy(const std::shared_ptr<PlayStrategy> & playStrategy)325 void DownloadMonitor::SetPlayStrategy(const std::shared_ptr<PlayStrategy>& playStrategy)
326 {
327 if (downloader_ != nullptr) {
328 downloader_->SetPlayStrategy(playStrategy);
329 }
330 }
331
SetInterruptState(bool isInterruptNeeded)332 void DownloadMonitor::SetInterruptState(bool isInterruptNeeded)
333 {
334 if (downloader_ != nullptr) {
335 downloader_->SetInterruptState(isInterruptNeeded);
336 }
337 }
338
GetStreamInfo(std::vector<StreamInfo> & streams)339 Status DownloadMonitor::GetStreamInfo(std::vector<StreamInfo>& streams)
340 {
341 return downloader_->GetStreamInfo(streams);
342 }
343
SelectStream(int32_t streamId)344 Status DownloadMonitor::SelectStream(int32_t streamId)
345 {
346 return downloader_->SelectStream(streamId);
347 }
348
GetDownloadInfo(DownloadInfo & downloadInfo)349 void DownloadMonitor::GetDownloadInfo(DownloadInfo& downloadInfo)
350 {
351 if (downloader_ != nullptr) {
352 MEDIA_LOG_I("DownloadMonitor GetDownloadInfo");
353 downloader_->GetDownloadInfo(downloadInfo);
354 }
355 }
356
GetDownloadInfo()357 std::pair<int32_t, int32_t> DownloadMonitor::GetDownloadInfo()
358 {
359 MEDIA_LOG_I("DownloadMonitor GetDownloadInfo");
360 if (downloader_ == nullptr) {
361 return std::make_pair(0, 0);
362 }
363 return downloader_->GetDownloadInfo();
364 }
365
GetPlaybackInfo(PlaybackInfo & playbackInfo)366 void DownloadMonitor::GetPlaybackInfo(PlaybackInfo& playbackInfo)
367 {
368 if (downloader_ != nullptr) {
369 MEDIA_LOG_I("DownloadMonitor GetPlaybackInfo");
370 downloader_->GetPlaybackInfo(playbackInfo);
371 }
372 }
373
GetBufferSize() const374 size_t DownloadMonitor::GetBufferSize() const
375 {
376 FALSE_RETURN_V(downloader_ != nullptr, 0);
377 return downloader_->GetBufferSize();
378 }
379
SetCurrentBitRate(int32_t bitRate,int32_t streamID)380 Status DownloadMonitor::SetCurrentBitRate(int32_t bitRate, int32_t streamID)
381 {
382 MEDIA_LOG_I("SetCurrentBitRate");
383 if (downloader_ == nullptr) {
384 MEDIA_LOG_E("SetCurrentBitRate failed, downloader_ is nullptr");
385 return Status::ERROR_INVALID_OPERATION;
386 }
387 return downloader_->SetCurrentBitRate(bitRate, streamID);
388 }
389
SetAppUid(int32_t appUid)390 void DownloadMonitor::SetAppUid(int32_t appUid)
391 {
392 if (downloader_) {
393 downloader_->SetAppUid(appUid);
394 }
395 }
396
GetPlayable()397 bool DownloadMonitor::GetPlayable()
398 {
399 if (downloader_) {
400 return downloader_->GetPlayable();
401 }
402 return false;
403 }
404
GetBufferingTimeOut()405 bool DownloadMonitor::GetBufferingTimeOut()
406 {
407 if (downloader_) {
408 return downloader_->GetBufferingTimeOut();
409 } else {
410 return false;
411 }
412 }
413
GetReadTimeOut(bool isDelay)414 bool DownloadMonitor::GetReadTimeOut(bool isDelay)
415 {
416 if (downloader_) {
417 return downloader_->GetReadTimeOut(isDelay);
418 }
419 return false;
420 }
421
GetSegmentOffset()422 size_t DownloadMonitor::GetSegmentOffset()
423 {
424 if (downloader_) {
425 return downloader_->GetSegmentOffset();
426 }
427 return 0;
428 }
429
GetHLSDiscontinuity()430 bool DownloadMonitor::GetHLSDiscontinuity()
431 {
432 if (downloader_) {
433 return downloader_->GetHLSDiscontinuity();
434 }
435 return false;
436 }
437
StopBufferring(bool isAppBackground)438 Status DownloadMonitor::StopBufferring(bool isAppBackground)
439 {
440 MEDIA_LOG_I("DownloadMonitor::StopBufferring");
441 if (downloader_ == nullptr) {
442 MEDIA_LOG_E("StopBufferring failed, downloader_ is nullptr");
443 return Status::ERROR_NULL_POINTER;
444 }
445 return downloader_->StopBufferring(isAppBackground);
446 }
447
WaitForBufferingEnd()448 void DownloadMonitor::WaitForBufferingEnd()
449 {
450 FALSE_RETURN_MSG(downloader_ != nullptr, "WaitForBufferingEnd downloader is nullptr");
451 downloader_->WaitForBufferingEnd();
452 }
453
GetServerMediaServiceErrorCode(int32_t errorCode,int32_t & serverCode)454 void DownloadMonitor::GetServerMediaServiceErrorCode(int32_t errorCode, int32_t& serverCode)
455 {
456 if (serverErrorCodeMap_.find(errorCode) == serverErrorCodeMap_.end()) {
457 MEDIA_LOG_W("Unknown server error code.");
458 } else {
459 serverCode = serverErrorCodeMap_[errorCode];
460 MEDIA_LOG_D("serverCode: " PUBLIC_LOG_D32, static_cast<int32_t>(serverCode));
461 }
462 }
463
GetClientMediaServiceErrorCode(int32_t errorCode,int32_t & clientCode)464 void DownloadMonitor::GetClientMediaServiceErrorCode(int32_t errorCode, int32_t& clientCode)
465 {
466 if (clientErrorCodeMap_.find(errorCode) == clientErrorCodeMap_.end()) {
467 MEDIA_LOG_W("Unknown client error code.");
468 } else {
469 clientCode = clientErrorCodeMap_[errorCode];
470 MEDIA_LOG_D("clientCode: " PUBLIC_LOG_D32, static_cast<int32_t>(clientCode));
471 }
472 }
473
SetInitialBufferSize(int32_t offset,int32_t size)474 bool DownloadMonitor::SetInitialBufferSize(int32_t offset, int32_t size)
475 {
476 return downloader_->SetInitialBufferSize(offset, size);
477 }
478
NotifyInitSuccess()479 void DownloadMonitor::NotifyInitSuccess()
480 {
481 FALSE_RETURN_MSG(downloader_ != nullptr, "NotifyInitSuccess downloader is nullptr");
482 downloader_->NotifyInitSuccess();
483 }
484
GetCachedDuration()485 uint64_t DownloadMonitor::GetCachedDuration()
486 {
487 FALSE_RETURN_V_MSG_E(downloader_ != nullptr, 0, "downloader_ is nullptr");
488 return downloader_->GetCachedDuration();
489 }
490
RestartAndClearBuffer()491 void DownloadMonitor::RestartAndClearBuffer()
492 {
493 FALSE_RETURN_MSG(downloader_ != nullptr, "downloader_ is nullptr");
494 return downloader_->RestartAndClearBuffer();
495 }
496
IsFlvLive()497 bool DownloadMonitor::IsFlvLive()
498 {
499 FALSE_RETURN_V_MSG_E(downloader_ != nullptr, false, "downloader_ is nullptr");
500 return downloader_->IsFlvLive();
501 }
502
SetStartPts(int64_t startPts)503 void DownloadMonitor::SetStartPts(int64_t startPts)
504 {
505 if (downloader_) {
506 downloader_->SetStartPts(startPts);
507 }
508 }
509
SetExtraCache(uint64_t cacheDuration)510 void DownloadMonitor::SetExtraCache(uint64_t cacheDuration)
511 {
512 if (downloader_) {
513 downloader_->SetExtraCache(cacheDuration);
514 }
515 }
516
SetMediaStreams(const MediaStreamList & mediaStreams)517 void DownloadMonitor::SetMediaStreams(const MediaStreamList& mediaStreams)
518 {
519 if (downloader_) {
520 downloader_->SetMediaStreams(mediaStreams);
521 }
522 }
523
IsHlsFmp4()524 bool DownloadMonitor::IsHlsFmp4()
525 {
526 FALSE_RETURN_V_MSG_E(downloader_ != nullptr, false, "downloader_ is nullptr");
527 return downloader_->IsHlsFmp4();
528 }
529
GetContentType()530 std::string DownloadMonitor::GetContentType()
531 {
532 FALSE_RETURN_V(downloader_ != nullptr, "");
533 return downloader_->GetContentType();
534 }
535
GetMemorySize()536 uint64_t DownloadMonitor::GetMemorySize()
537 {
538 FALSE_RETURN_V_MSG_E(downloader_ != nullptr, 0, "downloader_ is nullptr");
539 return downloader_->GetMemorySize();
540 }
541
GetCurUrl()542 std::string DownloadMonitor::GetCurUrl()
543 {
544 FALSE_RETURN_V(downloader_ != nullptr, "");
545 return downloader_->GetCurUrl();
546 }
547 }
548 }
549 }
550 }