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