1 /* 2 * Copyright (c) 2022-2022 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 #ifndef HISTREAMER_DOWNLOADER_H 17 #define HISTREAMER_DOWNLOADER_H 18 19 #include <functional> 20 #include <memory> 21 #include <string> 22 #include "foundation/osal/thread/task.h" 23 #include "foundation/osal/thread/mutex.h" 24 #include "foundation/utils/blocking_queue.h" 25 #include "foundation/osal/utils/util.h" 26 #include "network_client.h" 27 28 namespace OHOS { 29 namespace Media { 30 namespace Plugin { 31 namespace HttpPlugin { 32 enum struct DownloadStatus { 33 PARTTAL_DOWNLOAD, 34 }; 35 36 struct HeaderInfo { 37 char contentType[32]; // 32 chars 38 size_t fileContentLen {0}; 39 long contentLen {0}; 40 bool isChunked {false}; 41 bool isClosed {false}; 42 UpdateHeaderInfo43 void Update(const HeaderInfo* info) 44 { 45 (void)memcpy_s(contentType, sizeof(contentType), info->contentType, sizeof(contentType)); 46 fileContentLen = info->fileContentLen; 47 contentLen = info->contentLen; 48 isChunked = info->isChunked; 49 } 50 GetFileContentLengthHeaderInfo51 size_t GetFileContentLength() const 52 { 53 while (fileContentLen == 0 && !isChunked && !isClosed) { 54 OSAL::SleepFor(10); // 10, wait for fileContentLen updated 55 } 56 return fileContentLen; 57 } 58 }; 59 60 // uint8_t* : the data should save 61 // uint32_t : length 62 using DataSaveFunc = std::function<bool(uint8_t*, uint32_t)>; 63 class Downloader; 64 class DownloadRequest; 65 using StatusCallbackFunc = std::function<void(DownloadStatus, std::shared_ptr<Downloader>&, 66 std::shared_ptr<DownloadRequest>&)>; 67 68 class DownloadRequest { 69 public: 70 DownloadRequest(const std::string& url, DataSaveFunc saveData, StatusCallbackFunc statusCallback, 71 bool requestWholeFile = false); 72 size_t GetFileContentLength() const; 73 void SaveHeader(const HeaderInfo* header); 74 bool IsChunked() const; 75 bool IsEos() const; 76 int GetRetryTimes() const; 77 NetworkClientErrorCode GetClientError() const; 78 NetworkServerErrorCode GetServerError() const; IsSame(const std::shared_ptr<DownloadRequest> & other)79 bool IsSame(const std::shared_ptr<DownloadRequest>& other) const 80 { 81 return url_ == other->url_ && startPos_ == other->startPos_; 82 } GetUrl()83 std::string GetUrl() const 84 { 85 return url_; 86 } 87 bool IsClosed() const; 88 void Close(); 89 90 private: 91 void WaitHeaderUpdated() const; 92 93 std::string url_; 94 DataSaveFunc saveData_; 95 StatusCallbackFunc statusCallback_; 96 97 HeaderInfo headerInfo_; 98 99 bool isHeaderUpdated {false}; 100 bool isEos_ {false}; // file download finished 101 int64_t startPos_; 102 bool isDownloading_; 103 bool requestWholeFile_ {false}; 104 int requestSize_; 105 int retryTimes_ {0}; 106 NetworkClientErrorCode clientError_ {NetworkClientErrorCode::ERROR_OK}; 107 NetworkServerErrorCode serverError_ {0}; 108 109 friend class Downloader; 110 }; 111 112 class Downloader { 113 public: 114 explicit Downloader(std::string name) noexcept; 115 virtual ~Downloader(); 116 117 bool Download(const std::shared_ptr<DownloadRequest>& request, int32_t waitMs); 118 void Start(); 119 void Pause(); 120 void Resume(); 121 void Stop(bool isAsync = false); 122 bool Seek(int64_t offset); 123 bool Retry(const std::shared_ptr<DownloadRequest>& request); 124 private: 125 bool BeginDownload(); 126 127 void HttpDownloadLoop(); 128 void HandleRetOK(); 129 static size_t RxBodyData(void* buffer, size_t size, size_t nitems, void* userParam); 130 static size_t RxHeaderData(void* buffer, size_t size, size_t nitems, void* userParam); 131 132 std::string name_; 133 std::shared_ptr<NetworkClient> client_; 134 std::shared_ptr<OSAL::Task> task_; 135 std::shared_ptr<BlockingQueue<std::shared_ptr<DownloadRequest>>> requestQue_; 136 OSAL::Mutex operatorMutex_{}; 137 138 std::shared_ptr<DownloadRequest> currentRequest_; 139 bool shouldStartNextRequest {false}; 140 }; 141 } 142 } 143 } 144 } 145 #endif